ReactJs:防止多次按下按钮
ReactJs: Prevent multiple times button press
在我的 React 组件中,我有一个按钮,用于在单击时通过 AJAX 发送一些数据。我只需要第一次发生,即在第一次使用后禁用按钮。
我是如何尝试这样做的:
var UploadArea = React.createClass({
getInitialState() {
return {
showUploadButton: true
};
},
disableUploadButton(callback) {
this.setState({ showUploadButton: false }, callback);
},
// This was simpler before I started trying everything I could think of
onClickUploadFile() {
if (!this.state.showUploadButton) {
return;
}
this.disableUploadButton(function() {
$.ajax({
[...]
});
});
},
render() {
var uploadButton;
if (this.state.showUploadButton) {
uploadButton = (
<button onClick={this.onClickUploadFile}>Send</button>
);
}
return (
<div>
{uploadButton}
</div>
);
}
});
我认为发生的事情是状态变量showUploadButton
没有立即更新,React 文档说这是预期的。
我怎样才能强制按钮在被单击的那一刻被禁用或完全消失?
解决方案是在进入处理程序后立即检查状态。React 保证交互式事件(如点击)中的 setState 在浏览器事件边界处被刷新。参考: https://github.com/facebook/react/issues/11171#issuecomment-357945371
// In constructor
this.state = {
disabled : false
};
// Handler for on click
handleClick = (event) => {
if (this.state.disabled) {
return;
}
this.setState({disabled: true});
// Send
}
// In render
<button onClick={this.handleClick} disabled={this.state.disabled} ...>
{this.state.disabled ? 'Sending...' : 'Send'}
<button>
您可以做的是在单击后禁用按钮并将其保留在页面中(不可单击的元素)。
要实现这一点,您必须向按钮元素添加一个 ref
<button ref="btn" onClick={this.onClickUploadFile}>Send</button>
然后在点击上传文件功能上禁用按钮
this.refs.btn.setAttribute("disabled", "disabled");
然后,您可以相应地设置禁用按钮的样式,以便通过以下方式向用户提供一些反馈
.btn:disabled{ /* styles go here */}
如果需要,请确保使用
this.refs.btn.removeAttribute("disabled");
更新:在 React 中处理 refs 的首选方法是使用函数而不是字符串。
<button
ref={btn => { this.btn = btn; }}
onClick={this.onClickUploadFile}
>Send</button>
this.btn.setAttribute("disabled", "disabled");
this.btn.removeAttribute("disabled");
更新:使用反应钩子
import {useRef} from 'react';
let btnRef = useRef();
const onBtnClick = e => {
if(btnRef.current){
btnRef.current.setAttribute("disabled", "disabled");
}
}
<button ref={btnRef} onClick={onBtnClick}>Send</button>
下面是使用您提供的代码的小示例https://jsfiddle.net/69z2wepo/30824/
测试为工作:http://codepen.io/zvona/pen/KVbVPQ
class UploadArea extends React.Component {
constructor(props) {
super(props)
this.state = {
isButtonDisabled: false
}
}
uploadFile() {
// first set the isButtonDisabled to true
this.setState({
isButtonDisabled: true
});
// then do your thing
}
render() {
return (
<button
type='submit'
onClick={() => this.uploadFile()}
disabled={this.state.isButtonDisabled}>
Upload
</button>
)
}
}
ReactDOM.render(<UploadArea />, document.body);
你可以尝试使用 React Hooks 来设置组件状态。
import React, { useState } from 'react';
const Button = () => {
const [double, setDouble] = useState(false);
return (
<button
disabled={double}
onClick={() => {
// doSomething();
setDouble(true);
}}
/>
);
};
export default Button;
确保您使用的是^16.7.0-alpha.x
版本或更高版本的 react
和 react-dom
。
希望对您有所帮助!
如果你在onClick期间禁用按钮,你基本上会得到这个。一个干净的方法是:
import React, { useState } from 'react';
import Button from '@material-ui/core/Button';
export default function CalmButton(props) {
const [executing, setExecuting] = useState(false);
const {
disabled,
onClick,
...otherProps
} = props;
const onRealClick = async (event) => {
setExecuting(true);
try {
await onClick();
} finally {
setExecuting(false);
}
};
return (
<Button
onClick={onRealClick}
disabled={executing || disabled}
{...otherProps}
/>
)
}
在这里看到它的实际效果:https://codesandbox.io/s/extended-button-that-disabled-itself-during-onclick-execution-mg6z8
我们基本上扩展了按钮组件,增加了在onClick执行期间被禁用的额外行为。执行此操作的步骤:
- 创建本地状态以在执行时捕获
- 提取我们篡改的属性(禁用,onClick)
- 通过设置执行状态扩展单击操作
- 使用我们覆盖的 onClick 渲染按钮,并扩展禁用
注意:您应该确保原始的onClick操作是异步的,也就是它返回一个承诺。
如果你愿意,只需阻止提交。
使用lodash.js debounce
怎么样
将突发事件(如击键)分组为一个事件。
https://lodash.com/docs/4.17.11#debounce
<Button accessible={true}
onPress={_.debounce(async () => {
await this.props._selectUserTickets(this.props._accountId)
}, 1000)}
></Button>
通过使用 event.target
,您可以禁用单击的按钮。创建时使用箭头函数并调用函数onClick
。不要忘记在参数中传递事件。
查看我的代码笔
这是代码:
class Buttons extends React.Component{
constructor(props){
super(props)
this.buttons = ['A','B','C','D']
}
disableOnclick = (e) =>{
e.target.disabled = true
}
render(){
return(
<div>
{this.buttons.map((btn,index) => (
<button type='button'
key={index}
onClick={(e)=>this.disableOnclick(e)}
>{btn}</button>
))}
</div>
)}
}
ReactDOM.render(<Buttons />, document.body);
const once = (f, g) => {
let done = false;
return (...args) => {
if (!done) {
done = true;
f(...args);
} else {
g(...args);
}
};
};
const exampleMethod = () => console.log("exampleMethod executed for the first time");
const errorMethod = () => console.log("exampleMethod can be executed only once")
let onlyOnce = once(exampleMethod, errorMethod);
onlyOnce();
onlyOnce();
输出
exampleMethod executed for the first time
exampleMethod can be executed only once
您可以在 onClick 回调中获取元素引用并从那里setAttribute
,例如:
<Button
onClick={(e) => {
e.target.setAttribute("disabled", true);
this.handler();
}}
>
Submit
</Button>
保持简单和内联:
<button type="submit"
onClick={event => event.currentTarget.disabled = true}>
save
</button>
但!这也将禁用按钮,当表单校准失败时!因此,您将无法重新提交。
在这种情况下,二传手更好。
此修复了在窗体onSubmit
中设置禁用:
// state variable if the form is currently submitting
const [submitting, setSubmitting] = useState(false);
// ...
return (
<form onSubmit={e => {
setSubmitting(true); // create a method to modify the element
}}>
<SubmitButton showLoading={submitting}>save</SubmitButton>
</form>
);
按钮看起来像这样:
import {ReactComponent as IconCog} from '../../img/icon/cog.svg';
import {useEffect, useRef} from "react";
export const SubmitButton = ({children, showLoading}) => {
const submitButton = useRef();
useEffect(() => {
if (showLoading) {
submitButton.current.disabled = true;
} else {
submitButton.current.removeAttribute("disabled");
}
}, [showLoading]);
return (
<button type="submit"
ref={submitButton}>
<main>
<span>{children}</span>
</main>
</button>
);
};
另一种方法可能是这样的:
<button onClick={this.handleClick} disabled={isLoading ? "disabled" :""}>Send</button>
我的方法是,如果处理中的事件不执行任何内容。
class UploadArea extends React.Component {
constructor(props) {
super(props)
this.state = {
onProcess:false
}
}
uploadFile() {
if (!this.state.onProcess){
this.setState({
onProcess: true
});
// then do your thing
this.setState({
onProcess: false;
});
}
}
render() {
return (
<button
type='submit'
onClick={() => this.uploadFile()}>
Upload
</button>
)
}
}
ReactDOM.render(<UploadArea />, document.body);
尝试使用以下代码:
class Form extends React.Component {
constructor() {
this.state = {
disabled: false,
};
}
handleClick() {
this.setState({
disabled: true,
});
if (this.state.disabled) {
return;
}
setTimeout(() => this.setState({ disabled: false }), 2000);
}
render() {
return (
<button type="submit" onClick={() => this.handleClick()} disabled={this.state.disabled}>
Submit
</button>
);
}
}
ReactDOM.render(<Form />, document.getElementById('root'));
如果仍然有人面临此类问题,解决方案比创建自定义组件等要容易得多......
只
- 设置一个名为"默认禁用"的状态值 false。
- 将其分配给按钮的禁用属性。
- 在 onPress 中首先将其设置为 true,然后做你的事情....
- 然后在组件的 un mount 上将其设置为 false...
function MyClickable() {
const [disabled,setDisabled] = useState(false)
useEffect(() => {
return () => setDisabled(false)
},[])
const onPress = useCallback(() => {
setDisabled(true);
// do your stuff
},[]);
<TouchableOpacity disabled={disabled} onPress={onPress}>
// your things
</TouchableOpacity>
尝试使用此代码
<button
onClick={async (e) => {
e.currentTarget.disabled = true;
await onClickUploadFile();
e.currentTarget.disabled = false;
}}>
Upload
</button>
- 创建一个类似链接的按钮,并通过Javascript函数打开一个新的弹出窗口
- 正在添加'X'按钮,在文本字段旁边使用javascript
- 多个单选按钮组相互干扰
- 如何从reactjs中的按钮向函数传递props
- ReactJS:使用浏览器按钮导航时保存状态
- 当我在 reactjs 中单击按钮时如何加载函数
- ReactJS - 如何在单击按钮时添加更多文本、文本字段、选择字段
- ReactJs:防止多次按下按钮
- ReactJS:如何在单选按钮中使用布尔值
- ReactJS-将溢出的元素放入一个“"下拉按钮
- 在 ReactJs 中的按钮上切换活动类
- 显示ReactJS中显示模态的按钮列表
- ReactJS:显示或隐藏元素只在第一次点击按钮时起作用
- Reactjs的onClick:如何设置列表中被点击按钮的状态
- ReactJs为按钮添加活动类
- ReactJS:点击按钮来改变页面上的组件
- 从数据库中获取ReactJs按钮的初始状态
- ReactJS+Redux:如何使用Material UI's将按钮提升为<input/>
- Reactjs:在按钮的“点击”句柄上刷新页面
- 如何组合ReactJs的Router Link和material-ui组件(比如按钮)