Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React.memo and withRouter

I want to not re-render my component on certain paths, trying to do this using React.memo and checking the current path using the withRouter HOC.

The compare function in React.memo does not get called.

function compare(prevProps, nextProps) {
  console.log(prevProps,nextProps)
  return (prevProps.location.pathname !== '/' && nextProps.location.pathname !== '/')
}
export default React.memo( withRouter(MyComponent), compare);
like image 993
Abhiman Avatar asked May 22 '26 22:05

Abhiman


2 Answers

just use it like this

function compare(prevProps, nextProps) {
  console.log(prevProps,nextProps)
  return (prevProps.location.pathname == nextProps.location.pathname)
}
export default withRouter(React.memo(MyComponent, compare));

Take care for the comparison you are about to do

the comparison you had has a flow, if you are in the main page where the route is / then the compare function will always return false causing re-render all the time(just like if memo didn't exist in the first place), and if your are in a sub-route other than / like /articles then the comparison will always return true causing the component to re-render al the time, just like if memo didn't exist in the first place.

What you want is a comparison that depends on new and old props having equal things which leads to save a re-render or having non-equal things which leads to a new re-render to render the fresh data for you.

So the comparison should be something like

prevProps.location.pathname == nextProps.location.pathname
like image 72
Neo13 Avatar answered May 24 '26 10:05

Neo13


Thanks for your question, it was very helpful to me two months ago.

memo function take a component and a function that will be called to decide if React needs to re-render or not, if the function returns true the component will not re-render, any way if the function returns false then the props are now different and React do re-render to your component.

Now: to access the pathname correctly in the function passed to memo then memo should be wrapped with withRouter and not the opposite, withRouter wrap a component (it doesn't know it's memorized version of a component or not, it just wraps it) and pass it the routing props.

The function passed to memo as a second argument now can access the previous and new props and do the comparison as we talked earlier (where each props as inside it the fully routing details that you want).

import { memo } from 'react';

function propsAreEqualBasedOnPathname(prevProps, nextProps) {
    return prevProps.location.pathname == nextProps.location.pathname;
}

withRouter(memo(MyComponent), propsAreEqualBasedOnPathname);

Finally, take extra care for how the comparison is made inside the compare function because some mistakes might prevent your component from re-rendering in the future forever.

I found using memo with withRouter really important to improve the performance of React components, especially if the component was a page full of details and fetching logic that can cost you some time to render, so every re-render you save, increases your page performance.

like image 26
Mhd Louay Al-osh Avatar answered May 24 '26 11:05

Mhd Louay Al-osh



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!