> 文章列表 > useMemo hook

useMemo hook

useMemo hook

useMemo hook

useMemo 是个可以在重渲染的过程中缓存计算结果的 React Hook。memo 使用方法为:

const cachedValue = useMemo(calculateValue, dependencies);

其中 calculateValue 是一个计算过的值,一般的用法是一个由返回值的函数dependencies 是一个包含所有需要监控参数的数组,这个数组对于整个 memo 的过程来说非常的重要。useMemo 在第一次渲染时会返回 calculateValue,在其他的渲染过程中,如果 dependencies 产生变化,那么就会重新调用 calculateValue 函数,并返回重新计算过的值。

这其实也算是一个 gocha,因为之前项目中出现了一个 bug 就是由 useMomo 造成的。

大概流程是使用 useMemo 缓存了一个值传到了公司内部开发的 UI 库中,UI 库返回了正确的数值,但是在我们使用的 wrapper 中,该值被 cache 了,因此 dependency 没有变化的情况下它就不会被重新渲染。

大概的案例如下:

const UIWrapper = ({ initialValue }) => {const [value, setValue] = useState(initialValue);const cachedValue = useMemo(() => 'some value here', [initialValue]);const handleUpdateVal = (someVal) => {setValue(someVal);};return <UI cachedValue={cachedValue} handleUpdateVal={handleUpdateVal} />;
};

其中 cachedValuevalue 大概是在 UI 库中有一些依存关系,因此尽管 handleUpdateVal 中需要获取的值在 UI 中更新了,但是 handleUpdateVal 本身并没有被调用。因此,在使用第三方库时,使用 memoization 这个技巧还是需要更加的谨慎,并且需要判断数据之间是否存在依存关系,否则就有可能造成页面的不渲染。

其他一些 useMemo 的注意点

  1. useMemo 使用 Object.is() 进行判断

    因此如果传入的值是一个对象,那么 useMemo 依旧进行重新计算,如:

    const obj = { a: 'a' };console.log(Object.is(obj, { a: 'a' }));
    

    useMemo hook

    所以 useMemo 中不应该传入传入 useState 创建的对象——每次渲染 useState 都会创建一个新的对象,因此将这个值放入 useMemo 的依赖中就没有任何的意义。

    解决方案:可以使用 useMemo 去 memo 通过 useState 创建的对象本身。

  2. useState 可以用来 memo React 组件

  3. 如果要使用 useMemo 去 memo 一个函数,不如使用 useCallback

  4. 严格模式下 React 会渲染组件两次去判断函数是否为纯函数,这也是一个很好的 debug 方法去判断函数的输入和输出是否一致

  5. useMemo 只因 惊觉 🐔 你太美 作为一个性能提升的方法,如果不使用 useMemo 代码就无法正常工作,那么应该找到问题的关键,而不是依赖于 useMemo

    You should only rely on useMemo as a performance optimization. If your code doesn’t work without it, find the underlying problem and fix it first. Then you may add useMemo to improve performance.