Closed
Description
React version: 17.0.2
Steps To Reproduce
- Create a counter reducer with a top limit (top limit is set externally using a prop or state)
- Return the current state if the count reaches the top limit
- Try to increment the counter by calling
dispatch({type:'INCREMENT'})
a few times after the counter has reached the top limit - Set the top limit to a greater number
- You'll see that after increasing the top limit, the reducer callback will be called as much as you'd tried to increment the counter in step 3 and the counter will increment that much
Link to code example: CODE PEN
The current behavior
After setting the top limit to a higher limit, the previous INCREMENT
actions which are called before and the reducer have returned the intact state, will be called again and the reducer function will be called as much as you've tried before and the counter will increase that much.
The expected behavior
After setting the top limit to a higher limit, the previous INCREMENT
actions which are called before, must not be called again and the Reducer function must not be called again and the counter must stay the same.
Activity
eps1lon commentedon May 3, 2021
Thanks for the report.
If I click 2 more times it goes to 6 after increasing the limit. If I click 3 more times it goes to 7 after increasing the limit. But in your repro you say it should increase to 7. Did you either mean "it increases to 6" or "click three more times"?
I forked your repro into a codesandbox and simplified it to a primitive state so that we don't get distracted: https://codesandbox.io/s/react-17-reducer-prop-closure-548bh
Same behavior in React 16: https://codesandbox.io/s/react-16-reducer-prop-closure-forked-fxs5q?file=/src/index.js
hosseini44444 commentedon May 3, 2021
You're welcome!
Thanks for the quick response.
You're right, the first time when you set the limit to a greater number, the counter will go up the number of times you've incremented the counter minus one.
The interesting point is that if you click the increment button one extra time and then set the top limit to 10, then the counter will stay the same (5) but if then you set the top limit to 5 again and then click the increment button 1 more time and set the top limit to 10 again you'll see that the counter will increase to 6 this time.
It seems that calls to the reducer get batched.
hosseini44444 commentedon May 3, 2021
My current workaround around this is returning a new state by spreading the old state, instead of returning the old state.
Obviously, this approach will cause unnecessary reRenders.
[-]Bug: useReducer reducer function gets called twice (possible memory leak)[/-][+]Bug: useReducer, reducer function gets called twice (possible memory leak)[/+]a-c-sreedhar-reddy commentedon May 17, 2021
same as #17953
Navaneethan2503 commentedon Aug 19, 2021
i would like to work on this issue