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