question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

unexpected rerenders with selectById

See original GitHub issue

I have a hook which does a simple selectByID from the store.

// store

export const useTypedSelector = createSelectorHook<RootState>();

// hook

useCurrentStatus = (statusId: string) => {
  return useTypedSelector((state) =>
    apiStatusSelectors.selectById(state, statusId)
  );
}

Now for some reason when I render a component for the first time, all the components which have the same status id render as well.

I looked in the react profiler and it said these components were rendering because of hook changes.

So I manually diffed the hooks and found that one of the subhooks of selectById appears to be triggering the render.

    {
      "name": "SelectorWithStoreAndSubscription",
      "subHooks": [
        {
          "name": "Reducer",
          "value": 3,
          "subHooks": []
        },

Specifically the value on "SelectorWithStoreAndSubscription" increments whenever I render a new component.

Any ideas where "SelectorWithStoreAndSubscription" is coming from and why those values would be changing across components?

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5

github_iconTop GitHub Comments

1reaction
markeriksoncommented, Jan 27, 2021

Sorry, I’m a bit confused. selectById is a selector - it doesn’t have any “hooks” or “subhooks”. Are you referring to useSelector itself there? That counter looks like the internal value that useSelector uses to force a re-render. However, it only does that if the reference returned by your selector changes from the last time.

selectById is memoized, but ultimately comes down to a straight lookup: return state.entities[id], effectively. On the one hand, using the same selectById instance across multiple components will never memoize correctly, but because it’s a lookup, it shouldn’t actually matter on a per-component basis.

Can you put together a CodeSandbox that shows this issue?

0reactions
markeriksoncommented, Jan 28, 2021

ah, gotcha!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Why is the entire list re-rendered after updating one element in ...
And in post component I get all needed data with selectors: const post = useSelector((state) => postsSelector.selectById(state, postId)); ...
Read more >
4 options to prevent extra rerenders with React context
If useContext were to conditionally trigger rerenders, ... familyName }; default: throw new Error('unexpected action type'); } };.
Read more >
Redux Essentials, Part 6: Performance and Normalizing Data
The official Redux Essentials tutorial: learn how to improve app performance and structure data correctly.
Read more >
Preventing rerenders with React.memo and useContext hook.
I need to rerender component only if globalState contains nextProps.value }); ... introducing an "unexpected" behavior from the single case, ...
Read more >
How to debug unnecessary rerenders in React | Bryce's Blog
Common reasons for rerendering: Hooks changing (ie useState 's setState methode being called)
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found