To learn useMemo, you must know React.memo

Both of these have some optimization effects

The role of the memo

When the data changes, the code is executed again, but the child component is executed without changing the data. In this case, you can use memo to wrap the child component so that the data is executed only when the data changes

case

Click the button to change the value of n without changing m, and verify that the program will execute m’s code

Not using memo

When n is changed, m is not changed, but Child’s print statement is executed

function App(){
  const [n,setN] = useState(0);
  const [m,setM] = useState(0);
  
  const add=() = >{
    setN(i= >i+1);
  };
  const addChild=() = >{
    setM(i= >i+1);
  };
  
  return(
    <div>
      <div>
        n:{n}
        <button onClick={add}>n+1</button>
        <button onClick={addChild}>m+1</button>
      </div>
      <Child data={m} />
    </div>)}function Child(props){
  console.log('Child executed')
  return(
    <div>
      child:{props.data}
    </div>
      )
}
ReactDOM.render(<App />.document.getElementById('root'));
Copy the code

Use memo for encapsulation

If m does not change, then the Child component will not execute. If m does not change, then the Child component will not execute

Using the React. Memo wrapper returns a new component and calls the new component

function Child(props){
  console.log('Child executed')
  return(
    <div>
      child:{props.data}
    </div>)}/ / encapsulates the child
const Child2 = React.memo(Child)
ReactDOM.render(<App />.document.getElementById('root'));
Copy the code

If you add a listener function to the Child, it will execute the Child regardless of whether m is changed or not

function App(){
  const [n,setN] = useState(0);
  const [m,setM] = useState(0);
  const add=() = >{
    setN(i= >i+1);
  };
  const addChild=() = >{
    setM(i= >i+1);
  };
+  const onClickChild=() = >{};return(
    <div>
      <div>
        n:{n}
        <button onClick={add}>n+1</button>
        <button onClick={addChild}>m+1</button>
      </div>
+      <Child2 data={m} onClick={onClickChild} />
    </div>)}function Child(props){
  console.log('Child executed')
  console.log('There's a lot of code here.')
  return(+<div onClick={props.onClick}>
      child:{props.data}
    </div>)}const Child2 = React.memo(Child)
Copy the code

When n is clicked, the App code is reexecuted and the address of the empty onClickChild function is changed, so the Child is still executed

And that’s what useMemo does

The role of useMemo

To solve the problem of rendering yourself due to function updates, you can use useMemo, which rewraps functions

Const onClickChild=useMemo(fn,array) listens to variables. The first argument is a function and the second argument is a dependency. The function is recalculated only if the dependency changes

import React, { useMemo, useState } from 'react'
import ReactDOM from 'react-dom'

// The rest of the code is unchanged, just rewrite the click function of m

  // Use useMemo to rewrite the listener function so that it executes only when m changes
  const onClickChild=useMemo(() = >{
    return () = >{
      console.log(m)
    }
  },[m])
Copy the code

You can also replace useMemo with useCallback, using useCallback without writing a return function

const onClickChild=useMemo(() = >{
    return () = >{
      console.log(m)
    }
  },[m])
 / / equivalent to the
 const onClickChild=useCallback(() = >{
      console.log(m)
  },[m])
Copy the code

Note:

  • If your value is a function, then you have to writeuseMemo(()=>(x)=> console.log(x))
  • This is a function that returns a function, which is complicated; So there you have ituseCallback, you can useuseCallback