二约 React 的useCallback与useMemo

252 阅读2分钟

很多人不使用这俩,因为搞不清楚 useCallback和 useMemo 的实际作用,先说说这俩是做什么的。

简介 useCallbackuseMemo

1. useCallback

useCallback 主要作用,是为了优化渲染性能,避免过度渲染而存在的。当一个函数依赖某些状态,去做一些事情。但是当这些状态并没有变更的时候,就可以使用 useCallback来避免重新创建函数。最好是在依赖项比较多活着依赖项是函数的时候使用。

const memoizedCallback = useCallback(()=>{
    doSomething(a, b);
}, [a, b])

2. useMemo

useMemo的主要作用是为了缓存计算的结果,避免重复计算。有点像 vue中的 computed。当某个值需要变化的值来计算生成时,而且这个值又会在多个地方使用的时候,就应该想到 useMemo来缓存了。

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

这里说几个注意的点

  1. 怎么写全依赖项

    建议可以使用 ESLint 的插件 eslint-plugin-react-hooks检测。

  2. 对于依赖项

    建议使用具体的值,而不是函数作为依赖项。

    因为函数作为依赖项,还是会导致不必要的渲染。😭

  3. 不建议使用useCallback的时候

    • 同步执行的函数,不建议使用 useCallback, 因为没有必要缓存
      const memoizedCallback = useCallback(() => {
        doSomething(a, b);
      },[a, b]);
      
    • 异步执行的函数,建议配合 useEffect一起使用
      const MyComponent = ({ id }) => {
      
          const [data, setData] = useState(null);
          
          const fetchData = useCallback(async () => {
              const result = await fetch(`/api/data/${id}`);
              const data = await result.json();
              setData(data);
          }, [id]);
          
          useEffect(() => {
              fetchData();
          }, [fetchData])
          
          return {data};
       
      });
      

说点其他的

过渡渲染

react应用中,由于组件的状态或者属性的变化,引起组件频繁的重新渲染的情况。 当组件重新渲染时, react 会重新生成新的虚拟 DOM 树,并将其与旧的虚拟 DOM 数进行比较,从而确定需要更新哪些部分的实际DOM。这个过程消耗很大。

解决这种过度消耗的方式,上面讲的两种就在其中。

使用回调函数,可以降组件变化的依赖项直接传递给回调函数,而不是直接在组件中处理。故而,依赖的项先计算影响 DOM 渲染的数据,数据不变,不需要重新渲染。

除去上面说的两种之外, React.memo, React.PureComponent, shouldComponentUpdate也可以优化过去渲染。

结束了