Search code examples
reactjsfunctionreact-hooksusecallback

The increaseSecondState function is re-rendering the child component even when i didn't pass it as a prop to the child component


I didnt expect the child component to re-render because i didnt pass the increaseSecondState function as a prop to the child component. Because we all know after using React.memo on the child component, the only way it can re-render is if only its prop changes.

import React, { useState, useCallback } from 'react'
import Child from './Child'

function Example() {
  const [state, setState] = useState(0)
  const [count, setCount] = useState(0)

  const increaseFirstState = () => {
    setState(state + 1)
  }

  const increaseSecondState = () => {
    setCount(count + 1)
  }

  return (
    <div>
      <Child firstFunc={increaseFirstState} />
      <h1>first state - {state}</h1>
      <h1>second state - {count}</h1>

      <button onClick={increaseFirstState}>first state</button>
      <button onClick={increaseSecondState}>second state</button>
    </div>
  )
}

export default Example


Solution

  • Every time Example renders, a new increaseFirstState function gets created. It may have the same text as the previous one, but it's a different function. Since the firstFunc prop has changed, Child must rerender, even if it uses React.memo.

    To prevent the rerender, not only must you use react.memo, but you must also make sure the props don't change. You'll do this by using useCallback to memoize your functions.

    const increaseFirstState = useCallback(() => {
      setState(prev => prev + 1);
    }, []);
    
    const increaseSecondState = useCallback(() => {
      setCount(prev => prev + 1);
    }, []);