State variable not updating in useEffect callback?
See original GitHub issueDo you want to request a feature or report a bug? Bug, maybe? Although thinking about it more makes me think I’ve misunderstood something.
What is the current behavior?
scroll
state variable updates in rendered output but not inside handleScroll
event callback.
I reckon this might be due to the fact that when handleScroll
is defined scroll
is 0
, but scroll
is defined in the scope above and should be updated when the component is re-rendered.
import React, { useState, useEffect } from "react";
const Scroller = () => {
const [scroll, setScroll] = useState(window.scrollY);
const handleScroll = () => {
console.log(scroll); // scroll is always 0
setScroll(window.scrollY);
};
useEffect(() => {
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
}, []); // runs once
return <div id="scroll">{scroll}</div>; // scroll is correct
};
export default Scroller;
What is the expected behavior?
scroll
to be updated inside handleScroll
event callback and in render output.
Which versions of React, and which browser / OS are affected by this issue?
chrome 70.0.3538.77
react 16.7.0-alpha.0 - next
react-dom 16.7.0-alpha.0 - next
Issue Analytics
- State:
- Created 5 years ago
- Reactions:57
- Comments:27 (3 by maintainers)
Top Results From Across the Web
variable in useState not updating in useEffect callback
There are a couple of issues: You're not returning a function from useEffect to clear the interval; Your inc value is out of...
Read more >[Resolved] useState not showing updated value - Freaky Jolly
When trying to get the updated state from the child to parent component, it is not updating the latest value in the console...
Read more >Why React setState/useState does not update immediately
The answer: They're just queues ... React this.setState , and useState does not make changes directly to the state object. React this.setState ,...
Read more >variable in useState not updating in useEffect callback-Reactjs
The issue here is that the callback from clearInterval is defined every time useEffect runs, which is when count updates. The value inc...
Read more >Steps to Solve Changes Not Reflecting When useState Set ...
When the “useState” set method is not reflecting a change immediately, it may be due to the current closure of the state variable....
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
@evolutionxbox
It is not a bug, but the normal behavior from the doc. You can check this issue for more detail https://github.com/facebook/react/issues/14042
In short, if you are using the second parameter
[]
then you need to put all the variable (state or not) that you rely on.So in your case, if you want to have access to the
scroll
state variable then you need to put[scroll]
😃Obviously you maybe don’t want to do that, because you don’t want to create / remove event listener everytimes.
So the other way is to use an other effect, that will be responsible to modifying or getting the value.
useReducer
is one way. (see the other issue for code example)I hope it is clear 😃
Yep that’s right. We might offer a more convenient way in the future.
The rule of thumb is that if you use a variable in
useEffect
, you must declare it in theuseEffect
dependency array (or omit the array entirely). So in your examplehandleScroll
should be in the array.It’s true that this would cause it to re-subscribe more often. There is a way to avoid it but it’s not very convenient and might cause other issues in the future. We plan to add a better way later but it will take some time to implement.