Search code examples
reduxstateeasy-peasy

EasyPeasy store hook causes rerender upon any state change


We currently have a redux state with nested models with the following structure.

{
  groups: {
    ids: [],
    status: {},
    error: {}
  },
  members: {
    ids: [],
    status: {},
    error: {}
}

For convenience, each model has an exported hook, typed as;

export const useGroupState = () => useTypedState((state) => state.groups);

And used like so;

const { ids } = useGroupState()

We use this syntax throughout our app. However we recently noticed that upon any state change to the GroupState, even if it does not modify ids, causes a rerender. If Groups.status updates, anything destructing with the above syntax will rerender.

We solved this by using

const ids = useTypedState(({groups}) => groups.ids)

However, the old syntax is convenient and is fairly widespread. Is there a way we could retain the old syntax but fix the re-render behavior?

Thanks,


Solution

  • I don't know the exact implementation of the useTypedState hook here, but assuming it uses the React-Redux useSelector hook inside: yes, this is entirely expected behavior. useSelector re-renders if the returned reference has changed since last time. If you return an object, and that object gets immutably updated, then it's a new reference and will force a re-render. Destructuring only some of the fields happens after the render is in progress.

    Your component should always select the smallest amount of actual state that it needs.