Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible for button onClick to fire twice before being disabled since setState is asynchronous?

In the follow example, we have a button that starts and upload, and disables itself while the upload is in progress. It reenables itself when the upload is done.

Is it possible that, due to the asynchronous nature of React's setState, for a user that is clicking really fast, to trigger the onClick callback twice before the button is disabled?

Please do not answer with solutions for how to avoid this scenario, I want to know if this scenario if even possible in the first place and if so, how to reproduce it.

import React from 'react';
import ReactDOM from 'react-dom';

class App extends React.Component {
  constructor (props) {
    super(props)

    this.state = {
      uploadDisabled: false
    }
  }


  upload = () => {
    this.setState({
      uploadDisabled: true
    })

    fetch('/upload').then(() => {
      this.setState({
        uploadDisabled: false
      })
    })
  }

  render () {
    return (
      <div>
        <button disabled={this.state.uploadDisabled} onClick={this.upload}>
          Upload
        </button>
      </div>
    )
  }
}
like image 796
Transcendence Avatar asked Jan 04 '18 09:01

Transcendence


People also ask

What happens when setState is called?

The setState() schedule changes to the component's state object and tells React that the component and its children must rerender with the updated state: // Correct this. setState({name: 'Obaseki Nosa'});

How do you get double click event in React JS?

To handle double click events in React:Add an onClick prop to the element. Use the detail property on the event object to get the click count. If the click count is equal to 2, handle the double click event.

How prevent user from clicking button multiple times React?

To prevent multiple button clicks in React: Set an onClick prop on the button, passing it a function. When the button gets clicked, set its disabled attribute to true .

How many arguments does setState take and why is it async?

The setState method takes up to 2 arguments. We usually pass in only one. The first argument can be an object or a callback that's used to update the state. which calls setState once, and then calls setState again in the callback.


1 Answers

I'm not sure it's possible:

class Button extends React.Component {
  constructor(){
    super();
    this.state = {disabled: false};
    this.onClick = () => {
      this.setState({
        disabled: true
      });
      console.log('click')

      setTimeout(() => {
        this.setState({
          disabled: false
        });
      }, 1000)
    };
  }

  render() {
    return <button onClick={this.onClick} disabled={this.state.disabled}>foo</button>;
  }
}

ReactDOM.render(
  <Button/>,
  document.getElementById('container')
);

setTimeout(() => {
  const button = document.getElementsByTagName('button')[0]
  for(let i = 0; i < 2; i++) {
    button.click()
  }
}, 200)

https://jsbin.com/tamifaruqu/edit?html,js,console,output

It prints click only once

like image 123
iofjuupasli Avatar answered Oct 11 '22 15:10

iofjuupasli