background

First we define a Compound Component:

const App = (a)= > {
  console.log('App render.')
  const [count, setCount] = useState(0)
  const someValue = 'someValue'

  return (
    <div>
      <button onClick={() => setCount(prev=>prev+1)}>
        click to rerender
      </button>
      <CountDemo count={count} />
      <Demo someValue={someValue} />
    </div>
  )
}
Copy the code

The two sub-components are:

const CountDemo = ({count}) = > {
  console.log('count render.')
  return (
    <div>
      <p>{count}</p>
    </div>)}const Demo = (a)= > {
  console.log('Demo render.')
  return (
    <div>Demo</div>)}Copy the code

When we click the button, the console displays:

"App render."
"count render."
"Demo render."
Copy the code

You can see that both CountDemo and Demo are re-rendered, but in reality, only CountDemo needs to be updated.

memo

React.memo can be used to avoid duplicate rendering of the Demo component:

/ / use the React. Memo
const Demo = memo((a)= > {
  console.log('Demo render.')
  return (
    <div>React.memo</div>)})Copy the code

Click the button, the console displays:

"App render."
"count render."
Copy the code

Avoid unnecessary rerendering of the demo.

useCallback

What if, instead of primitive type data, the child component is passed a function?

const App = (a)= >{... const someValue ='someValue'
const someFunc = (a)= > someValue
 ...
    <Demo someFunc={someFunc} />
 ...
}

const Demo = memo(({someFunc}) = >{... return (<div>{someFunc()}</div>)})Copy the code

Click the button, the console displays:

"App render."
"count render."
"Demo render."
Copy the code

Because the react. memo uses shallowly compare by default, and the function is referential data, the parent component will generate a different someFunc every time it rerenders, which will cause the demo to rerender. So, you can use useCallback to return a memoized callback:

const App = (a)= >{...// With useCallback, someValue changes when someValue changes
const someFunc = useCallback((a)= > someValue, [someValue])
 ...
    
}
Copy the code

Click the button at this point and the Demo component will not be rendered unnecessarily repeatedly.

useMemo

If an object is passed in and the object is a reference, like useCallback, we can use useMemo to avoid unnecessary rerendering:

const App = (a)= >{... const someValue ='someValue'
const someObj = useMemo((a)= > ({ value: someValue }), [someValue])
 ...
    <Demo someFunc={someFunc} />
 ...
}

const Demo = memo(({someObj}) = >{... return (<div>{someObj.value}</div>)})Copy the code

Online sample

See the Pen React Demo by eehong (@eugene930) on CodePen.

reference

Hooks API Reference

Hooks Cheatshhet