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.

Context.Provider as HOC with memoized children - children still rerender on any state change

See original GitHub issue

here is my setup:

const Screen = withVideoPlayer(() => {
      const load = useContextSelector(VideoPlayerContext, c => c.load);

      console.log("Screen rerendered")
  ...
})
const withVideoPlayer = <P extends object>(WrappedComponent: FC<P>) => {
    const ComponentWithPlayerContext = (props: P) => {
        const controller = useInitVideoPlayerController();

        const Memoized = useMemo(() => memo(WrappedComponent), [WrappedComponent]);

        return (
            <VideoPlayerContext.Provider value={controller}>
                <Memoized {...props} />
            </VideoPlayerContext.Provider>
        );
    };

    return ComponentWithPlayerContext;
};
const useInitVideoPlayerController = () => {

  const load = useCallback(
        async (
            video: IVideo | IVideoTrailer,
            options?: Partial<{
                autoplay: boolean;
                position: number;
            }>,
        ) => {
            dispatch({ type: 'load', payload: { video, options } });
        },
        [],
  );

  ...

  return {
      ... a bunch of state properties and methods wrapped with useCallback
      load,
  };
}

the problem is the Screen component rerenders any time the context is changed, even though it only uses “load” method which is wrapped with useCallback without dependencies. If i remove const load = useVideoPlayer(c=>c.load) from Screen, the rerenders don’t happen anymore.

could this be related to this? https://github.com/dai-shi/use-context-selector/issues/86

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
lightrowcommented, Oct 7, 2022

so i assume if we used React’s own Context, it would always go to phase 2?

1reaction
dai-shicommented, Oct 7, 2022

Yes, that is an expected behavior. React render has two phases, 1) render phase for invoking render function and b) commit phase to apply changes to DOM. What you see with console.log in the render function is 1) and what you see in useEffect is 2). It impacts on performance if your render function is computationally heavy. In such cases, you want to use useMemo and/or React.memo to avoid extra computations.

Read more comments on GitHub >

github_iconTop Results From Across the Web

prevent child component to re-render below context provider ...
So I want to prevent my child components to rerender. I tried using React.memo() but it's still rendering whenever I set the state...
Read more >
Preventing rerenders with React.memo and useContext hook.
Now any change of AppContext won't re-render ThemeContext ... Our component would still re-execute, but React wouldn't re-render the child ...
Read more >
How did I re-render: Sharing State through React-Context
But, the child component that should not be functionally dependent upon the 'lifted' state will re-render when the state changes.
Read more >
React components - when do children re-render?
At first glance, the answer is obvious - React children will re-render when either their props/state change or their parent component re-renders ...
Read more >
React re-renders guide: everything, all at once - Developer way
There are four reasons why a component would re-render itself: state changes, parent (or children) re-renders, context changes, and hooks  ...
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