Do you want to request a feature or report a bug?
report a bug
What is the current behavior?
When I call setState with a callback in a test using react shallow renderer (via enzyme), the callback gets called and this.state
is still the old state.
EDIT: This seems limited to componentWillMount
If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://jsfiddle.net or similar (template for React 16: https://jsfiddle.net/Luktwrdm/, template for React 15: https://jsfiddle.net/hmbg7e9w/).
EDIT: Reproduce with this https://github.com/bdwain/setstate-callback-bug
What is the expected behavior?
When the setState callback gets called, it should have access to the new state.
Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
Version 16.
It worked in v15 with enzyme 2.
EDIT: I think this is because in componentWillMount, this line causes the render method in the shallow wrapper to return early, before it updates the state.
Thanks for the report.
Note that using setState callback in componentWillMount doesn't make a lot of sense to me. You should just use conponentDidMount instead it you can.
I agree. I generally never use componentWillMount. The one reason I can see to use componentWillMount is because it lets you share logic that calls setState with other parts of the component. I was just upgrading my project to react 16 and noticed some places where it was used that had this issue. While they all could be implemented a different way, I feel like it's not incorrect and makes sense to behave as expected.
Yeah that's fair!
Wanna take a stab at adding a failing test and fixing it?
I think what needs to be done is that instead of calling the callback
in enqueue*
methods immediately we should store it on a field, and then call it when we have finished mounting or updating.
Yea I can take a look. I may not have time to finish it today though. Not sure if it’s important to finish before 16.1. Since it’s not too hard to use the constructor or componentdidmount instead I feel like it’s not a huge deal though, especially if a patch release can be done before 16.2. I already changed the spots in my project that were breaking and it was pretty easy.
We've already cut 16.1. Seems okay since it probably was broken in 16.0 too.
Hi, @gaearon and @bdwain –
I was taking a look at this issue earlier and I might have come up with a test to reproduce this bug and a patch to fix it.
As this is assigned @bdwain I didn’t want to step in his shoes and send a PR, but I’m happy to push the code so you guys can take a look and maybe get some insights – is this ok?
Not a problem. I haven’t had a chance to do anything yet. Lets just go with yours.
Thanks @bdwain – just sent a PR :)
I had the same issue in React Native, was forced to re-use the new state variable like this:
const newState = "I'm new"
this.setState({ value: newState }, () => console.log(newState))
>> I'm new
If I didn't i would
const newState = "I'm new"
this.setState({ value: newState }, () => console.log(this.state))
>> I'm old
"dependencies": {
"react": "16.3.0-alpha.1",
"react-native": "0.54.0",
...
Using "react": "^16.3.2", I am still experiencing the same problem. The callback to setState has access to the old state..
I am also experiencing this. setState callback doesn't work as expected. Can you reopen this?
Can confirm - only adding that for whatever reason it was working before lifting to 16.4, so it feels like a regression.
I would open a new issue if the bug has resurfaced. Maintainers don't typically look at notifications from closed issues.
After some further analysis it seems that it was an unintended interplay with "getDerivedStateFromProps". Still need to get used to the new patterns emerging
@flq Do you mean this is working as intended, or there is indeed a regression issue?
It appears to work as advertised, i.e., the sequence is setSate - getDerivedStateFromProps - setState callback. If you overwrite your state in the „derived“ static, you have to expect weirdness.
Anyone still experiencing this behaviour please checkout this article on SO -- https://stackoverflow.com/questions/45339038/setstate-callback-not-waiting-for-state-to-update You may be using the callback argument incorrectly.
Most helpful comment
Using "react": "^16.3.2", I am still experiencing the same problem. The callback to setState has access to the old state..