preface

By default, the parent component’s state changes and it rerenders not only itself but also its children. So React invented useMemo & useCallback to help you cut down on unnecessary renderings.

In addition, shouldComponentUpdate/React.pureComponent/React.memo does something similar.

useMemo

const UseMemoPage = props= > {
  const [counter, setCounter] = useState(0)
  const [value, setValue] = useState(' ')
  const total = () = > {
    console.log('computed')
    let result = 0
    for (let i = 0; i < counter; i++) {
      result += i
    }
    return result
  }
  console.log(UseMemoPage.name, 'render')
  return (<>
    <p>{value}</p>/* When you change the value of the input, it also triggers an unnecessary operation of total, */<input value={value} onChange={(e)= > setValue(e.target.value)} />
    {total()}
    <button onClick={()= > setCounter(counter + 1)}>add</button>
  </>)}// console.log UseMemoPage render
// console.log computed
Copy the code
  • With useMemo improvements, changes to value do not trigger recalculationIn addition, useMemo can return a React component, which has the same effect
  const total = useMemo(() = > {
    console.log('computed')
    let result = 0
    for (let i = 0; i < counter; i++) {
      result += i
    }
    return result
  }, [counter])

// console.log UseMemoPage render
Copy the code

useCallback

const UseCallbackPage = props= > {
  const [counter, setCounter] = useState(0)
  const [value, setValue] = useState(' ')
  const addClick = () = > {
    console.log(addClick.name, 'render')
    setCounter(state= > state + 1)}console.log(UseCallbackPage.name, 'render')
  return (<>
    <p>{value}</p>
    <input value={value} onChange={(e)= > setValue(e.target.value)} />
    <button onClick={()= > setCounter(counter + 1)}>add</button>
    <Child counter={counter} addClick={addClick}></Child>
  </>)}const Child = React.memo((props) = > {
  console.log('Child'.'render')
  return (<div onClick={props.addClick}>{props.counter}</div>)})// console.log UseMemoPage render
// console.log Child render
Copy the code
  • If you use react.memo, however, when the value is updated, it will generate a new addClick(just the same name), which will render the Child component. This is when the useCallback comes into play, which will cache your function
  const addClick = useCallback(() = > {
    console.log(addClick.name, 'render')
    setCounter(state= > state + 1)}, [])// console.log UseCallbackPage render
Copy the code

Conclusion:

  1. UseCallback, useMemo looks like a patch for React, but it works fineReduce unnecessary rendering
  2. UseMemo returns an object, which generally applies to the component itself
  3. UseCallback returns a function that can be used with React. Memo to reduce Child rendering
  4. Therefore, the subcomponents should be as stateless as possible to facilitate development/testing/optimization