# Definition
  
  
  React.memo
- A higher order component that can be used to get some performance boost if a component renders the same results given the same 
props - Checks for prop changes, and skips rendering the component, and reuse the last rendered result in case previous and current 
propsare the same 
function PizzaComponent({ name, price }) {
  /* render using props */
  return (
    <div>Pizza: {name}</div>
    <div>Total: ${price}</div>
  )
}
export default React.memo(PizzaComponent);
This component is a candidate for memoization as given a ๐ image, it always renders the same ๐ details.
- By default, it does a shallow comparison of 
props - For custom control on 
propscomparison, a custom comparison function can be provided as a second argument. 
Let's extend our PizzaComponent to also show different toppings available for a ๐. Toppings will be an array of strings. As mentioned above, React.memo does a shallow comparison of props, so, in this case, even though the toppings array remains same, it will still re-render.
So, how do we fix this?
We pass a custom comparison function as follows:
function PizzaComponent({ name, price, toppings }) {
  function areEqual(prevProps, nextProps) {
    /*
    return true if passing nextProps to render would return
    the same result as passing prevProps to render,
    otherwise return false
    */
    return (
      prevProps.name === nextProps.name,
      prevProps.price === nextProps.price,
      prevProps.toppings.every(topping => nextProps.toppings.includes(topping))
    )
  }
  /* render using props */
  return (
    <div>Pizza: {name}</div>
    <div>Total: ${price}</div>
    {toppings.map((topping, index) => (
      <div key={`${name}_${topping}`}>{topping}</div>
    ))}
  )
}
export default React.memo(PizzaComponent, areEqual);
# Using React memo
Use React.memo to get a performance boost when:
- Component re-renders often
 - Component is usually provided with the same 
propsduring re-rendering - Component contains a relevant amount of elements to reason 
propsequality check 
If a component with hooks is wrapped with
React.memo, then it will still re-render when state or context changes.
# React memo with function as props
Let's add the functionality to order a ๐ in our PizzaComponent called onOrder as follows:
function PizzaComponent({ name, price, toppings, onOrder }) {
  function areEqual(prevProps, nextProps) {
    /*
    return true if passing nextProps to render would return
    the same result as passing prevProps to render,
    otherwise return false
    */
    return (
      prevProps.name === nextProps.name,
      prevProps.price === nextProps.price,
      prevProps.toppings.every(topping => nextProps.toppings.includes(topping))
    )
  }
  /* render using props */
  return (
    <div>Pizza: {name}</div>
    <div>Total: ${price}</div>
    {toppings.map((topping, index) => (
      <div key={`${name}_${topping}`}>{topping}</div>
    ))}
    <button onClick={onOrder}>Order</button>
  )
}
export default React.memo(PizzaComponent, areEqual);
and let's use it as follows:
function App ({ store }) {
  const { pizza } = store;
  return (
    <PizzaComponent
      name={pizza.name}
      price={pizza.price}
      toppings={pizza.toppings}
      onOrder={() => placeOrder(pizza.price, pizza.coupon)}
    />
  )
}
Since, React.memo does a shallow comparison, this will do a re-render everytime as it will see the callback function onOrder as a new prop everytime.
To fix this, we can wrap the function passed to onOrder with useCallback as follows:
function App ({ store }) {
  const { pizza } = store;
  /**
   * This will always return the same function instance as long as pizza is the same.
   */
  const onOrder = useCallback(
    () => placeOrder(pizza.price, pizza.coupon),
    [pizza],
  );
  return (
    <PizzaComponent
      name={pizza.name}
      price={pizza.price}
      toppings={pizza.toppings}
      onOrder={onOrder}
    />
  )
}
    
Top comments (0)