Javascript ReactJs:防止多次按下按钮

Javascript ReactJs:防止多次按下按钮,javascript,reactjs,react-jsx,Javascript,Reactjs,React Jsx,在React组件中,我有一个按钮,用于在单击时通过AJAX发送一些数据。我只需要在第一次使用时使用,即在第一次使用后禁用按钮 我是如何做到这一点的: var UploadArea = React.createClass({ getInitialState() { return { showUploadButton: true }; }, disableUploadButton(callback) { this.setState({ showUp

在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>
    );
  }

});
var UploadArea=React.createClass({
getInitialState(){
返回{
showUploadButton:真
};
},
禁用上载按钮(回调){
this.setState({showUploadButton:false},回调);
},
//在我开始尝试我能想到的一切之前,这是比较简单的
onClickUploadFile(){
如果(!this.state.showUploadButton){
返回;
}
此.disableUploadButton(函数()为){
$.ajax({
[...]
});
});
},
render(){
var上传按钮;
if(this.state.showUploadButton){
上传按钮=(
发送
);
}
返回(
{上传按钮}
);
}
});
我认为发生的是状态变量
showUploadButton
没有立即更新,React文档说这是预期的


我如何强制按钮在被单击时被禁用或同时消失?

您可以做的是在单击按钮后将其禁用,并将其保留在页面中(不可单击元素)

要实现这一点,您必须向button元素添加ref

<button ref="btn" onClick={this.onClickUploadFile}>Send</button>
然后,您可以相应地设置禁用按钮的样式,以便使用

.btn:disabled{ /* styles go here */}
如果需要,请确保使用重新启用它

this.refs.btn.removeAttribute("disabled");
更新:在React中处理ref的首选方法是使用函数而不是字符串

<button 
  ref={btn => { this.btn = btn; }} 
  onClick={this.onClickUploadFile}
>Send</button>


this.btn.setAttribute("disabled", "disabled");
this.btn.removeAttribute("disabled");
{this.btn=btn;}
onClick={this.onClickUploadFile}
>发送
此.btn.setAttribute(“禁用”、“禁用”);
此.btn.removeAttribute(“禁用”);
更新:使用react钩子

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>
从'react'导入{useRef};
设btnRef=useRef();
const onBtnClick=e=>{
如果(btnRef.当前){
btnRef.current.setAttribute(“禁用”、“禁用”);
}
}
发送
下面是一个使用您提供的代码的小示例

作为工作件进行测试:

class UploadArea扩展了React.Component{
建造师(道具){
超级(道具)
此.state={
isButtonDisabled:false
}
}
上传文件(){
//首先将isButtonDisabled设置为true
这是我的国家({
isButtonDisabled:正确
});
//那就做你的事
}
render(){
返回(
this.uploadFile()}
disabled={this.state.isButtonDisabled}>
上传
)
}
}
render(,document.body);

解决方案是在进入处理程序后立即检查状态。React保证在浏览器事件边界处刷新交互事件(如单击)中的setState。参考:

//在构造函数中
此.state={
禁用:false
};
//单击时的处理程序
handleClick=(事件)=>{
如果(此.state.disabled){
返回;
}
this.setState({disabled:true});
//发送
}
//渲染中
{this.state.disabled?'Sending…':'Send'}

如果需要,只需阻止提交即可

如何使用
lodash.js debounce

将突发事件(如击键)分组为单个事件

{
等待此.props.\u选择用户票证(此.props.\u帐户ID)
}, 1000)}
>
您可以尝试使用设置

import React,{useState}来自“React”;
常量按钮=()=>{
const[double,setDouble]=useState(false);
返回(
{
//doSomething();
setDouble(真);
}}
/>
);
};
导出默认按钮;
确保您使用的是
^16.7.0-alpha.x
版本或更高版本的
react
react dom

希望这对你有帮助

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();
输出


如果在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}
        />
    )
}

import React,{useState}来自“React”;
从“@material ui/core/Button”导入按钮;
导出默认功能按钮(道具){
const[executing,setExecuting]=useState(false);
常数{
残废
onClick,
…其他道具
}=道具;
const onRealClick=async(事件)=>{
setExecuting(true);
试一试{
等待onClick();
}最后{
设置正在执行(假);
}
};
返回(
)
}
请在此处查看它的实际操作:

我们基本上扩展了按钮组件,并在onClick执行期间禁用了额外的行为。执行此操作的步骤:

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>
    );
  }

});
  • 如果我们正在执行,则创建要捕获的本地状态
  • 提取我们篡改的属性(禁用,onClick)
  • 通过设置执行状态扩展onClick操作
  • 使用覆盖的onClick和扩展的disabled呈现按钮

  • 注意:您应该确保原始onClick操作是异步的,也就是说它返回承诺。

    通过使用
    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);
    
    类按钮扩展React.Component{
    建造师(道具){
    超级(道具)
    this.buttons=['A','B','C','D']
    }
    disableOnclick=(e)=>{
    e、 target.disabled=true
    }
    render(){
    返回(
    {this.buttons.map((btn,索引)=>(
    this.disableOnclick(e)}
    >{btn}
    ))}
    )}
    }
    render(,document.body);
    
    您可以在onClick回调中获取元素引用,并从此处获取
    setAttribute
    ,例如:

          <Button
            onClick={(e) => {
              e.target.setAttribute("disabled", true);
              this.handler();
            }}            
          >
            Submit
          </Button>
    
    {
    e、 target.setAttribute(“已禁用”,true);
    this.handler();
    }}            
    >
    提交
    
    这无法解决问题,因为React会取消状态更新通知。因此,总有一个延迟
    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
    
    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}
            />
        )
    }
    
    
    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);
    
          <Button
            onClick={(e) => {
              e.target.setAttribute("disabled", true);
              this.handler();
            }}            
          >
            Submit
          </Button>