I’m using setTimeout()
(I even tried driftless too) to change buttons from disabled = true
to disabled = false
3 seconds after appearing on the DOM (onLoad=
). The buttons appear in sequence, after the previous button has been clicked.
The problem is, the setTimeout()
goes absolutely haywire: Each button’s disabled = true
duration is seemingly sporadic (at least on Windows Chrome on 2 different PC’s). Sometimes the button seemingly waits the full 3 seconds to enable, sometimes it enables instantaneously, and everything in-between.
What is causing this inconsistency, and how can I get each button to enable exactly 3 seconds (well, within a couple hundred milliseconds…not a big deal) after appearing?
Javascript
import React from 'react' import ReactDOM from 'react-dom' export default class MyForm extends React.Component { constructor(props) { super(props); this.state = { is_button_disabled: true, show_button_1: true, show_button_2: false, show_button_3: false, show_button_4: false }; } handleDisableButton = (event) => { setTimeout(() => this.setState({ is_button_disabled: false }), 3000); } handleShowButton = (buttonId) => { if (buttonId === 'button_1'){ this.setState({ is_button_disabled: true}) this.setState({ show_button_1: false, show_button_2: true}) } if (buttonId === 'button_2'){ this.setState({ is_button_disabled: true}) this.setState({ show_button_2: false, show_button_3: true}) } if (buttonId === 'button_3'){ this.setState({ is_button_disabled: true}) this.setState({ show_button_3: false, show_button_4: true}) } if (buttonId === 'button_4'){ this.setState({ is_button_disabled: true}) this.setState({ show_button_4: false, show_button_1: true}) } } render() { const { show_button_1, show_button_2, show_button_3, show_button_4 } = this.state; return ( <div butttons> {show_button_1 && <button onLoad={this.handleDisableButton()} onClick={() => this.handleShowButton('button_1')} disabled={this.state.is_button_disabled}>Button1</button> } {show_button_2 && <button onLoad={this.handleDisableButton()} onClick={() => this.handleShowButton('button_2')} disabled={this.state.is_button_disabled}>Button2</button> } {show_button_3 && <button onLoad={this.handleDisableButton()} onClick={() => this.handleShowButton('button_3')} disabled={this.state.is_button_disabled}>Button3</button> } {show_button_4 && <button onLoad={this.handleDisableButton()} onClick={() => this.handleShowButton('button_4')} disabled={this.state.is_button_disabled}>Button4</button> } </div> ) } } ReactDOM.render(<MyForm />, document.getElementById('root'));
HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="theme-color" content="#000000"> <link rel="manifest" href="%PUBLIC_URL%/manifest.json"> <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"> <title>React App</title> </head> <body> <noscript> You need to enable JavaScript to run this app. </noscript> <div id="root"></div> </body> </html>
Advertisement
Answer
You should fix this first.
<button id="myButton" onLoad={this.handleDisableButton} onClick={() => this.handleShowButton('button_1')} disabled={this.state.is_button_disabled}>Button1</button>
which means
this.handleDisableButton()
to
this.handleDisableButton
And clearTimeout
to prevent memory leak
I have fixed your sandboxcode:
componentDidMount() { this.timeoutHandler = setTimeout(() => { clearTimeout(this.timeoutHandler); this.setState({ is_button_disabled: false }); }, 3000); } handleShowButton = (buttonId) => { let newState = {}; if (buttonId === "button_1") { newState = { is_button_disabled: true, show_button_1: false, show_button_2: true }; } if (buttonId === "button_2") { newState = { is_button_disabled: true, show_button_2: false, show_button_3: true }; } if (buttonId === "button_3") { newState = { is_button_disabled: true, show_button_3: false, show_button_4: true }; } if (buttonId === "button_4") { newState = { is_button_disabled: true, show_button_4: false, show_button_1: true }; } this.setState(newState, () => { this.timeoutHandler = setTimeout(() => { clearTimeout(this.timeoutHandler); this.setState({ is_button_disabled: false }); }, 3000); }); }; componentWillUnmount() { clearTimeout(this.timeoutHandler); }