Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
123
rated 0 times [  124] [ 1]  / answers: 1 / hits: 133234  / 6 Years ago, sat, october 27, 2018, 12:00:00

I'm trying out the new React Hooks and have a Clock component with a time value which is supposed to increase every second. However, the value does not increase beyond one.




function Clock() {
const [time, setTime] = React.useState(0);
React.useEffect(() => {
const timer = window.setInterval(() => {
setTime(time + 1);
}, 1000);
return () => {
window.clearInterval(timer);
};
}, []);

return (
<div>Seconds: {time}</div>
);
}

ReactDOM.render(<Clock />, document.querySelector('#app'));

<script src=https://unpkg.com/[email protected]/umd/react.development.js></script>
<script src=https://unpkg.com/[email protected]/umd/react-dom.development.js></script>

<div id=app></div>




More From » reactjs

 Answers
9

The reason is because the callback passed into setInterval's closure only accesses the time variable in the first render, it doesn't have access to the new time value in the subsequent render because the useEffect() is not invoked the second time.


time always has the value of 0 within the setInterval callback.


Like the setState you are familiar with, state hooks have two forms: one where it takes in the updated state, and the callback form which the current state is passed in. You should use the second form and read the latest state value within the setState callback to ensure that you have the latest state value before incrementing it.



Bonus: Alternative Approaches


Dan Abramov goes in-depth into the topic about using setInterval with hooks in his blog post and provides alternative ways around this issue. Highly recommend reading it!





function Clock() {
const [time, setTime] = React.useState(0);
React.useEffect(() => {
const timer = window.setInterval(() => {
setTime(prevTime => prevTime + 1); // <-- Change this line!
}, 1000);
return () => {
window.clearInterval(timer);
};
}, []);

return (
<div>Seconds: {time}</div>
);
}

ReactDOM.render(<Clock />, document.querySelector('#app'));

<script src=https://unpkg.com/[email protected]/umd/react.development.js></script>
<script src=https://unpkg.com/[email protected]/umd/react-dom.development.js></script>

<div id=app></div>




[#53236] Wednesday, October 24, 2018, 6 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
juancarlos

Total Points: 580
Total Questions: 105
Total Answers: 103

Location: Grenada
Member since Sun, Dec 20, 2020
3 Years ago
;