react-redux icon indicating copy to clipboard operation
react-redux copied to clipboard

Component does not re-render when changing a value

Open dylanwulf opened this issue 1 year ago • 7 comments

What version of React, ReactDOM/React Native, Redux, and React Redux are you using?

  • React: 18.2.0
  • ReactDOM: 18.2.0
  • Redux Toolkit: 1.9.6
  • React Redux: 8.1.2

What is the current behavior?

I have a value in my redux store and a component subscribed to that value via useSelector. I have encountered a scenario where changing the value does not re-render my component: https://codesandbox.io/s/react-redux-not-re-rendering-on-value-change-rzf3n4?file=/src/App.js

What is the expected behavior?

Changing the value should re-render my component

Which browser and OS are affected by this issue?

No response

Did this work in previous versions of React Redux?

  • [X] Yes

dylanwulf avatar Sep 28 '23 16:09 dylanwulf

Still running into this one and it's super strange (and not easy to recognize in most cases).

Looking at the linked codesandbox, if we comment out the local state change, it works as expected:

  const [lastSortDirection, setLastSortDirection] = useState(sortDirection);
  if (lastSortDirection !== sortDirection) {
    // Setting state directly in the render method is an approach recommended in the react docs:
    // https://react.dev/learn/you-might-not-need-an-effect#adjusting-some-state-when-a-prop-changes
    // setLastSortDirection(sortDirection);
  }

With that line uncommented, the action seems to be dispatched properly, the reducer appears to function, the redux store seems to be updating as expected - but the component isn't re-rendering.

I was thinking it could be an issue with @reduxjs/toolkit, but I'm not sure since rolling react-redux to version 7.2.9, the codesandbox appears to work properly.

cc: @markerikson

kgregory avatar Oct 12 '23 15:10 kgregory

Unfortunately this is low priority for me atm. All my attention is focused on getting RTK 2.0 and the associated major versions out the door.

My first guess would be something about useSyncExternalStore and rendering timing, but that's just a guess.

markerikson avatar Oct 12 '23 15:10 markerikson

My first guess would be something about useSyncExternalStore and rendering timing, but that's just a guess.

Thanks for taking the time to look at this and also for suggesting a direction. I appreciate the response.

kgregory avatar Oct 12 '23 16:10 kgregory

Looking into this a bit, I noticed that the issue occurs when setting state back to its initial value. If we change the initial value to something other than ASC, the component re-renders as expected.

That led me to react issue #25565, which appears to be merged, but describes the issue exactly:

Steps To Reproduce

  • Have a component use useSyncExternalStore (for example redux 8)
  • Call setState outside of useEffect or event handlers (in render)
  • Trigger a change to the store back and forth

The current behavior

  • The component does re-render if the store value is updated to something different than its initial value
  • The component does not re-render if the store is updated to its initial value again

So I created a reproduction that doesn't use redux in any way, based on a test that was referenced in that issue and it seems like this is in fact an issue with react, but one that will be fixed in 18.3.0 (switching between 18.2.0 and the latest 18.3 canary release toggles between broken and fixed): https://codesandbox.io/s/react-not-rerendering-v32s9x?file=/src/App.js

As a sanity check, I tried switching react and react-dom from 18.2.0 to the latest 18.3 canary in the codesandbox provided by @dylanwulf and the behavior works as expected.

kgregory avatar Oct 12 '23 17:10 kgregory

Yeah, I wondered if it was something like that. I knew I'd seen a couple issues along those lines (and ironically I seem to have commented in that one), but dind't remember specifics.

markerikson avatar Oct 12 '23 18:10 markerikson

That led me to https://github.com/facebook/react/issues/25565, which appears to be merged, but describes the issue exactly:

Oh nice find, that does sound like the same issue

dylanwulf avatar Oct 12 '23 19:10 dylanwulf

Just to keep this issue updated, the newly released react version 18.3.1 DOES NOT contain a fix for this issue. This issue is fixed in react canary only.

dylanwulf avatar May 09 '24 21:05 dylanwulf