Search code examples
javascriptreactjstypescriptmemoizationreact-functional-component

usage of React.memo() inside components with prop functions


import React, { useState } from 'react'

const App = () => {
  const [count, setCount] = useState<number>(0);
  const [otherCount, setOtherCount] = useState<number>(0);

  const increment = () => {
    setCount((pre) => {
      return pre + 1
    })
  }

  const decrease = () => {
    setOtherCount((pre) => {
      return pre - 1
    })
  }
  return (
    <>
      <DecrementComponent decrease={decrease} />
      <br />
      <br />
      <IncrementComponent increment={increment} />
    </>
  )
}

const DecrementComponent = React.memo(({ decrease }: { decrease: () => void; }) => {
  console.log("DecrementComponent");
  return (
    <div>
      <button onClick={decrease}>Decrement</button>
    </div>
  )
})

const IncrementComponent = React.memo(({ increment }: { increment: () => void; }) => {
  console.log("IncrementComponent");
  return (
    <div>
      <button onClick={increment}>Increment</button>
    </div>
  )
})

export default App

Although I used React.memo(), when I clicked increment or decrement functions, two components were rendered. But I think one component should be rendered in this scenario.

Why were two component rendered ?


Solution

  • React.memo can only help if the props don't change. But the increment and decrement functions change on every render, so the props are always changing. You will need to memoize those functions so that they don't change.

    const increment = useCallback(() => {
      setCount((pre) => {
        return pre + 1
      });
    }, []);
    
    const decrement = useCallback(() => {
      setCount((pre) => {
        return pre - 1
      });
    }, []);