-
Notifications
You must be signed in to change notification settings - Fork 47.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
State variable not updating in useEffect callback? #14066
Comments
It is not a bug, but the normal behavior from the doc. You can check this issue for more detail #14042 In short, if you are using the second parameter So in your case, if you want to have access to the 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. 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 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. |
I filed #14099 to track the root problem. |
I had same kind of problem when trying to add an eventListener to a component. For now, could be a better approach to stay with classes in these circumstances? |
@gpietro It seems like it. Current behavior just feels broken and the "workarounds" to achieve something as simple as this are just not worth it. |
I'm having the same problem so I won't open a new issue for it. Hopefully someone here can help me out with it. Here's the code:
And the console output on initial render of the whole app:
Then when I open the component that uses the labelWidth value the entire console becomes:
useEffect isn't updating the labelWidth property after mount. I've followed the instructions above so I'm not sure what the issue is. Any help? |
I think you want to use useState if you want it to be consistent.
|
@TidyIQ : had a similar issue recently, but using two hooks that shared a global and changing the value of it in each one. The value change/assignment is not persisted across useEffect invocations (there's even a warning that says that), probably related to memoization or caching/storing of the initial variable value when the hook function is created. The warning suggested using useRef to store the value used across useEffect calls but couldn't get it to work. Ended up ditching useEffect completely, used plain functions to set input/component values on every render. Given useEffect fires after the render, my issue was related to a slider component onChange firing to adjust for the accepted value range, setting the wrong state and ruining the workflow by (unwanted) firing another re-render. Is there a recommended way to update state or globals, using hooks, before the render happens? |
if you need a real unmount, not the crapy fake one that you find in all the examples and a one that has the correct state ... add this to your hook function :D 100% fix :D In you hook function:
|
almost same problem. I am updating the global state using context api, but when I am calling global state in |
I had the exact same problem in my branch. I solved it similar to this, but I don't think it is nice at all. Looking forward to the next update.
|
I'm having a similar issue
In the above code, I want to call useEffect callback only when count (coming from props) updates and I'm increasing inc in setInterval callback till it becomes equal to count. Now the issue is setInc is incrementing the value of inc but in useEffect's and setInterval's callback, I'm always getting 0, which I think should get updated as inc is in the closure these callbacks |
You’re not including all dependencies in the array. Try putting |
I can't do that, as I've setInterval in useEffect, if I put inc in array it will be infinite loop of setIntervals |
You might need to rethink what it does then. If you don’t include Why not use a Also I’m not sure it’s worth putting a prop as a dependency of the useEffect. |
It's a counter, it takes a value (max value) in props, then initializes inc with 0 and keeps increment inc till inc become equals to count, so I can't use setTimeout ( as it will execute call back first time only ) in my case I've put count in array because count value is coming from API call in parent component so count is initially 0, which I can solve by loading counter component only after getting data from server, So count in array is not an issue I can remove its dependency, my issue is why inc is not getting update in setInterval's callback Like if I use class component I can access updated inc from this.state.inc and will get the updated value but in case of functional component I'm not able to achieve the same |
It’s likely that when you wrote the class component it had a bug in it which you didn’t notice. The functional hook version is forcing you to face that bug first, not later. Try using a normal variable inside the useEffect rather than using state? |
Here is the class version
Like above in componentDidMount I'm able to get updated value of inc, I want the same thing using functional component, can you help to achieve the same using functional component I can't use a normal variable, as react is not going to render Counter component on it's update |
@gaearon any comments? |
include |
@AyWa 's solution worked for me (i.e using a reducer) However I was able to solve a similar issue (subscribing once in useEffect and updating state in callback) while still using useState(), alongside with the "function updater" option of the state update function as mentioned here: |
Swapping
See live demo: https://codesandbox.io/s/brave-kalam-j7xkb |
In case if you see stale or older values of state or props in useEffect callback or in event handlers, React suggests you to use refs keep the update values. This behavior is not due to React but its due to what values of a variable a javascript function receive at run-time (lexical scope and closures). React devs have tried to address this issue here: https://reactjs.org/docs/hooks-faq.html#why-am-i-seeing-stale-props-or-state-inside-my-function My opinion, the approach in the above doc solves the issue but seems a bit of a life hack. There are more quirks like this with hooks, so I still would prefer a class-based components for writing components with complex state and business logic. |
To anyone coming to this conversation late (like me). I ended up using
It can then be used in my form component:
The key is to |
We've submitted a proposal to solve this. Would appreciate your input! |
|
Do 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 insidehandleScroll
event callback.I reckon this might be due to the fact that when
handleScroll
is definedscroll
is0
, butscroll
is defined in the scope above and should be updated when the component is re-rendered.Please have a play:
What is the expected behavior?
scroll
to be updated insidehandleScroll
event callback and in render output.Which versions of React, and which browser / OS are affected by this issue?
The text was updated successfully, but these errors were encountered: