Suppose there’s the following simple component. When I click on the button, the message will change to Clicked
for 1 second and then goes back to -
. However, when I spam the button, I want the title to be Clicked
but it should go back to -
after the last click of the button. Basically, I want each click to expand the timeout.
If this was a simple JS function, I would just clear the interval after each click and set another timeout. However, I’m not sure how to achieve the same result using react hooks.
JavaScript
x
34
34
1
import ReactDOM from 'react-dom';
2
import {useEffect, useState} from 'react';
3
import './index.css';
4
5
const Test = () => {
6
const [message, setMessage] = useState("-");
7
8
const buttonClick = () => {
9
setMessage("Clicked");
10
}
11
useEffect(() => {
12
if(message !== "-") {
13
const id = setTimeout(() => {
14
console.log("Running Interval");
15
setMessage("-");
16
}, 1000);
17
18
return () => {
19
console.log("Clearing Interval");
20
clearTimeout(id);
21
}
22
}
23
}, [message]);
24
25
return (
26
<article>
27
<header>
28
{message}
29
</header>
30
<button onClick={buttonClick}>button</button>
31
</article>
32
);
33
}
34
Advertisement
Answer
Put the timeout ID into a ref, and then you can call clearTimeout
on it at the very beginning of the click handler.
JavaScript
1
23
23
1
const Test = () => {
2
const [message, setMessage] = React.useState("-");
3
const timeoutIdRef = React.useRef();
4
const handleClick = () => {
5
setMessage("Clicked");
6
clearTimeout(timeoutIdRef.current);
7
timeoutIdRef.current = setTimeout(() => {
8
setMessage("-");
9
}, 1000);
10
};
11
// cleanup, if desired
12
// React.useEffect(() => clearTimeout(timeoutIdRef.current), []);
13
return (
14
<article>
15
<header>
16
{message}
17
</header>
18
<button onClick={handleClick}>button</button>
19
</article>
20
);
21
}
22
23
ReactDOM.render(<Test />, document.querySelector('.react'));
JavaScript
1
3
1
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
2
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
3
<div class='react'></div>