Demand scenario
Sometimes, some calculations may be complex and time-consuming, or because the function component itself is not divided into mount and update, that is, as long as setState is called, the re rendering of the component will be triggered, regardless of whether the values of the front and rear states are different. In addition, when the parent component is updated, the child component will also be updated automatically. In order to consider performance, how to control some functions or states? These functions or states can only perform the calculation of these functions when they meet certain conditions (i.e. after some data changes), rather than every component rendering, which affects the performance. In fact, in most cases, due to the high efficiency of react, the performance problem can not be considered temporarily, It's not too late to optimize when necessary.
useMemo: it is used to cache the data obtained from complex calculations to avoid recalculation every rendering. Recalculation is only required when the dependency changes. It is equivalent to caching the computer result, that is, the computer result has a memory address and the dependency has not changed. It can be directly referenced every rendering.
useCallback: used to cache functions to avoid releasing memory and reallocating memory resources. Most of them are used to control sub components and will not be re rendered due to changes in this function. In fact, the cache is the memory reference address of the function.
characteristic
- The usage is similar to that of useEffect, but the function is essentially different. useEffect is a side effect function, that is, it is executed after component rendering (it can be controlled), useMemo and useCallback are originally functions that will be executed during each rendering (as long as you define and reference them in the function component, as long as setState will re render the component and cause it to execute. How to control the dependency remains unchanged, it will not execute.
- Both useMemo and useCallback are designed to improve performance and avoid indiscriminate calculation time-consuming functions during component rendering (and this function does not need to be recalculated if most of the time dependencies of this function do not change).
- useMemo and useCallback accept the same parameters. The first parameter is the callback function and the second parameter is the dependency value group.
- It is the function of cache. After calculation, the cache will be recalculated only when the dependency changes. useMemo caches the calculation data and useCallback caches the function.
- useCallback is more often used for the rendering control of parent and child components, and the re rendering of parent components. Sometimes it is not necessary to re render child components. The child components receive a function as props. At this time, useCallback can avoid the re rendering of child components.
- The function package of complex calculation is taken as its first parameter.
- Whether the functions of useMemo or useCallback perform operations unrelated to rendering, such operations with side effects belong to the applicable scope of useEffect.
Official advice: first write code that can be executed without useMemo and useCallback, and then consider them when optimizing performance as needed.
grammar
useMemo syntax:
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
useCallback syntax:
const memoizedCallback = useCallback( () => { doSomething(a, b); }, [a, b], );
Usage example
useMemo example:
function Example() { const [count, setCount] = useState(1); const [val, setValue] = useState(''); const getNum = useMemo(() => { return Array.from({length: count * 100}, (v, i) => i).reduce((a, b) => a+b) }, [count]) return <div> <h4>the sum:{getNum()}</h4> <div> <button onClick={() => setCount(count + 1)}>+1</button> <input value={val} onChange={event => setValue(event.target.value)}/> </div> </div>; }
useCallback example:
function Parent() { const [count, setCount] = useState(1); const [val, setValue] = useState(''); const getNum = useCallback(() => { return Array.from({length: count * 100}, (v, i) => i).reduce((a, b) => a+b) }, [count]) return <div> <Child getNum={getNum} /> <div> <button onClick={() => setCount(count + 1)}>+1</button> <input value={val} onChange={event => setValue(event.target.value)}/> </div> </div>; } const Child = React.memo(function ({ getNum }: any) { return <h4>the sum:{getNum()}</h4> })