I notice that some of my components are rerendering when I wouldn't expect them to. Lets say I have a <Header />
component. <Header />
calls useSelector
, and grabs a slice of state. As an example, my whole redux store may look like this:
{
header: "header slice",
body: "body slice"
}
<Header />
grabs what it needs with use selector:
const Header = () => {
const headerSlice = useSelector(state => state.header);
return <div>{headerSlice}</div>;
}
Elsewhere in the application, something causes the body
slice to update. When this happen, I see that <Header />
rerenders. This is not what I would expect. Why might this be happening?
For more detail, I was able to track this down by running the devtools profiler while triggering the action that updates state.body
. I see that <Header />
rerenders, and my profiler tells me its due to "Hooks 4, 9, 14, 19, and 24" changed.
When I look at that component's hooks in devtools, I see that all these hooks seem to be part of a Selector -> SyncExternalStoreWithSelector:
But there's not much information here to tell me which selector or was, what the previous value was, etc. When I remove these selectors, the unnecessary rerenders stop. But the values that this component consumes are not the values that are updating. I have tried wrapping the component in React.memo, and it makes no difference. I have not experienced this problem before with redux. Usually store updates only cause rerenders in those components that useSelect
updated values.
I am using react 18.2.0, redux 4.2.0, react-redux 8.0.2, and webpack 5.