Search code examples
reactjsreact-hooksreact-memo

how to use React.memo with a Component contains children


I have two Components, and I wrapped Parent with React.memo:

Child

const Child = ()=> <div>I'm Child</div>

export default Child

Parent

const Parent = (props)=> <div>{props.children}</div>

export default React.memo(Parent)

Use in App:

const App = () => {
  const [count, setCount] = useState(0)

  return(
    <div>
      <button onClick={()=>setCount(count+1)}></button>

      <Parent>
        <Child></Child>
      </Parent>
    </div>
  )
}

Click the button, result:

The Parent Component will rerender, so the memo not working because it's children is a function component

So, how can I prevent rerender?

I know a way to solve by useMemo, but it's ugly and not friendly, do you have better ideas?

const App = () => {
  const [count, setCount] = useState(0)

  const children = useMemo(()=><Child></Child>,[])

  return(
    <div>
      <button onClick={()=>setCount(count+1)}></button>

      <Parent>
        {children}
      </Parent>
    </div>
  )
}

Solution

  • Wrap your <Child /> with React.memo:

    const Child = ()=> {
      console.log('render') // fires only once - on initial render
      return <div>I'm Child</div>
    }
    
    const MChild = React.memo(Child);
    const Parent = (props)=> <div>{props.children}</div>
    const MParent = React.memo(Parent)
    
    const App = () => {
      const [count, setCount] = useState(0);
    
      return(
        <div>
          <button onClick={()=>setCount(count+1)}>increment {count}</button>
          <MParent>
            <MChild></MChild>
          </MParent>
        </div>
      )
    }
    
    render(<App />, document.getElementById('root'));