useMemo与useCallback

前提

  1. 两者都是接受两个参数fn、deps,然后返回缓存,为了避免非必要的渲染。
  2. 不同的是useMemo返回函数运行的结果,useCallback返回一个函数:
useCallback(fn, deps) --> useMemo(() => fn, deps);
复制代码
  1. 也就是说useMemo会把传入的函数执行,拿到结果缓存起来。而useCallback是把整个函数缓存起来,至于几时更新这个缓存,就要看第二个参数。
  2. 第二个参数与useEffect中用法一致。

例子

// useMemo
const [count, setCount] = useState(1);

const nodes = useMemo(() => {
    return (
        <em style={{paddingRight: '30px'}}>查询{count}</em>
    )
}, [count]);

const getNodes = useCallback(() => {
    return (
        <em style={{paddingRight: '30px'}}>查询{count}</em>
    )
}, [count]);


return (
    <div>
        <div onClick={() => setCount(count + 1)}>{count}</div>
        { nodes }
        { getNodes() }
    </div>
)
复制代码
  1. 上面的例子nodes跟getNodes效果是一样的。
  2. 当然并不是说两个的用法都可以互换,他们使用场景还是不一致的:
function Child({getCount}) {

    return (
        <div>{getCount()}</div>
    )
};

function Parent() {
    const [count, setCount] = useState(1);
    const [number, setNumber] = useState(1);
    
    const getCount = useCallback(() => {
         return Array.from({length: count * 100}, (v, i) => i).reduce((a, b) => a+b)
    }, [count]);
    return (
        <div>
            <Child getCount={getCount} number={number} />

            <div onClick={() => setCount(count + 1)}>计算: {count}</div>
            <div onClick={() => setNumber(number + 1)}>数字: {number}</div>
        </div>
    )
}


复制代码

1,点击”数字”按钮时sunCount、getCount都不会被重新渲染,如果不使用useCallback,sunCount、getCount都会重新渲染,即父组件传递一个函数给子组件的时候,由于父组件的更新会导致该函数重新生成从而传递给子组件的函数引用发生了变化,子组件也会重新渲染。

function Child({getCount, number}) {

    const curNumber = useMemo(function () {console.log('--number --')
        return <h4>数字:{number}</h4>
    }, [number]);
    
    return (
        <div>{getCount()}{curNumber}</div>
    )
};

function Parent() {
    const [count, setCount] = useState(1);
    const [number, setNumber] = useState(1);
    
    const getCount = useCallback(() => {
         return Array.from({length: count * 100}, (v, i) => i).reduce((a, b) => a+b)
    }, [count]);
    return (
        <div>
            <Child getCount={getCount} number={number} />

            <div onClick={() => setCount(count + 1)}>计算: {count}</div>
            <div onClick={() => setNumber(number + 1)}>数字: {number}</div>
        </div>
    )
}

复制代码
  1. 点击”计算”按钮,虽然Child重新渲染,但是curNumber并没有。

综上useCallback适用于缓存需要计算的函数,useMemo适用于缓存某个时刻组件的状态

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享