With the recent release of React Hooks, I've switched over to using more and more functional components in my React code. While reading the React docs, I kept seeing mentions of useReducer
being "more performant" than useState
. I was unclear on why so I did a deep dive into the topic. After much research and experimentation, these are my findings.
It's pretty hard to demonstrate these concepts without a video, but hopefully this content makes sense. I recommend using the React Dev Tools and turning on Highlight Updates
in the settings to test things out. It's also helpful to put a console.log on the Child component, if you see the console log, then it's being re-rendered.
Our Scenario: A Parent component with a Child component that receives props from the Parent. Assume that both are functional components and the Parent is using useState
to manage state.
If the props being passed to the Child component are simple, the Child should be wrapped with React.memo
to prevent re-renders if the props don't change. React.memo
will automatically optimize the functional component and acts like the shouldComponentUpdate
lifecycle method. Read more about React.memo.
If the Parent component is passing a function (specifically, a function that updates the state of the Parent) down to the Child component, only using React.memo
will not work. The function in the Parent component will need to be wrapped with the useCallback
hook. This is because the function will be "re-rendered" every time the Parent re-renders, so the Child will always consider that function a new prop. Read more about useCallback.
If the useReducer
hook is used in the Parent component to manage state, then we won't have to worry about useCallback
. useReducer
will return a dispatch
method that can be passed down to the Child component. The dispatch
method won't be "re-rendered" every time the Parent re-renders. Read more about useReducer.
When working with deeply nested Child components, it is recommended to use the useReducer
hook in conjunction with React Context. You can pass the dispatch
method down the tree with Context, which prevents prop drilling. Read more about this pattern.