Memo

Usage scenario: an App component has M and N data. There is also a Child component that accepts an M as its external data. So when we hit the n+1 button, we know that the App is going to execute again, is the Child going to execute again?

function App() { const [n, setN] = React.useState(0); const [m, setM] = React.useState(0); const onClick = () => { setN(n + 1); }; return ( <div className="App"> <div> <button onClick={onClick}>update n {n}</button> </div> <Child data={m}/> </div> ); } function Child(props) {console.log(" Child performed "); Console. log(' assuming there's a lot of code here ') return <div>child: {props. Data}</div>; }Copy the code

By typing log in the Child component, we see that the Child will also execute once if we change n. Why should Child be executed when it only depends on m and n changes? How to solve this problem?

You can use React. Memo to encapsulate the Child

const Child2 = React.memo(Child);
Copy the code

Put the Child in react. memo and you get Child2. Child2 is the function optimized for Child. Render this Child2 in your App

Result: Change n, Child is not executed, only if change m, the external data it depends on.

Make the code simpler: Place the anonymous function component directly in the Memo as an argument to get the Child component.

Const Child = React. Memo ((props)=>{console.log(" Child executed "); Console. log(' assuming there's a lot of code here ') return <div>child: {props. Data}</div>; });Copy the code

conclusion

React has extra render by default. When changing the data in a component, the component itself will execute again, causing the component’s children to execute again.

The react. memo makes a component execute only if the props it depends on change.

The memo has a bug

If the child component accepts a function, the function is defined in the parent component and passed to the child component. When I change n in the parent component, App() will definitely execute again. This will cause the function defined inside to execute as well.

function App() { const [n, setN] = React.useState(0); const [m, setM] = React.useState(0); const onClick = () => { setN(n + 1); }; Const onClickChild=()=>{} Return (<div className="App"> <div> <button onClick={onClick}>update n {n}</button> </div> <Child data={m} onClickChild={onClickChild}/> </div> ); } const Child = React. Memo ((props)=>{console.log(" Child executed "); return <div onClick={props.onClickChild}>child: {props.data}</div>; });Copy the code

Result: Click the button to change n. The Child does not depend on n, but the Child executes it.

React assumes that the onClickChild function has been redefined when the App is executed again. The content is the same, but the address is different. If the props accepted by the Child changes, it will execute again.

What to do? Can I have this function, in some cases, not regenerate and continue to use the last cached result

Use useMemo to achieve function reuse

const onClickChild = useMemo(() => {
    return () => {};
  }, [m]);
Copy the code

Put this function through useMemo optimization. UseMemo takes two arguments. The first argument is a function that returns the logic of the function itself. The second argument is a dependency, which means that the function is rebuilt only if m changes. If the dependent m does not change, the previous cache is reused and no new function is generated.

When the n+1 button is clicked, the Child component is not executed. Because we used useMemo to specify that the props function is regenerated only when M changes. M hasn’t changed, and even if App executes it again, this function won’t generate a new one.

UseMemo is often used to cache values that are expected to be used during two iterations of the old and new components.

Sometimes the thing that you want to cache, which is the return doesn’t have to be a function, it can be an object

The first argument to useMemo :()=> value, no parameter, returns a value. The second argument: depends on [m,n]. The new value is computed only when the dependency changes. The dependency does not change, reuse the previous value

UseMemo features:

  • The first argument is ()=>value
  • The second parameter is dependency[m,n]
  • Only when the dependency changes will the new value be recalculated
  • If the dependency does not change, reuse the previous value
  • Computations similar to Vue2

Note: If your value is a function, write

UseMemo (() = > (x) = > console. The log (x))Copy the code

This is a function that returns a function

Think it’s hard to use, then useCallback is coming

Usage of useCallback (grammar sugar for useMemo)

UseCallback (x =>console.log(x), [m])Copy the code

Is equivalent to

UseMemo (()=>(x)=>console.log(x), [m])Copy the code