欢迎光临散文网 会员登陆 & 注册

React手册 Hooks 之 useCallback

2023-04-28 10:54 作者:海里我最大  | 我要投稿

描述

    React 官网对 useCallback 的描述原文

useCallback is a React Hook that lets you cache a function definition between re-renders.

useCallback 是一个 React Hook,可以在你重新渲染之间缓存函数的定义.

    当你在渲染一个函数组件的时候, 如果在组件内部又声明了函数, 那么使用 useCallback 来包装这个内部函数可以缓存该函数引用, 避免每次重新渲染都获取到新函数.


 场景

    React: 默认情况下,当一个组件重新渲染时,React 会递归地重新渲染它的所有子组件

  因此当父组件状态变化时, 很多时候大部分子组件都是不必重新渲染的, React.memo 就是专门解决这种问题的一个方法, 被 React.memo 包装后的组件, 每次渲染会对所有 props 浅对比, 如果没有变化, 则不进行重新渲染, 从而提升性能, 但是如果传递的 props 是一个函数, 且这个函数还是在父组件内部创建的, 那么父组件每次渲染时给子组件传递的函数都是一个新的函数引用, 这时 React.memo 会认为 props 发生变化并重新渲染, 起不到优化的作用.

  useCallback 就是为了解决这个 React.memo 优化失效的问题, 它会在父组件外部缓存函数, 当父组件渲染时, 会返回函数的缓存, 让 React.memo 能拿到相同的函数引用, 从而让优化生效.

    在类组件中, 因为可以通过 this 来获取同一个方法引用来避免这个问题.

    

    接口定义:


参数

  • fn: Function

      需要缓存的函数, React 并不会调用它, 通常情况下是一个需要传递给子组件的函数, 缓存的意义也是为了避免子组件不必要的渲染.

  • dependencies: Array<mixed>

      缓存函数 fn 的时候, 需要告诉 useCallback 何时更新缓存, dependencies 里的状态发生变化的时候, 就会使缓存的函数进行更新, 当没有传 dependencies 的时候, useCallback 始终返回一个新函数, 这样也会让 React.memo 的优化失效, 所以一定要传, 当传入的是一个空数组的时候, 为依赖项始终是空, 不到, 所以渲染之后缓存无法再更新.

返回

    返回一个函数引用, 如果 dependencies 没有发生变化, 那么拿到的就是缓存中的函数引用, 反之会拿到一个新的函数引用.


用法1

    配合 React.memo 对子组件的渲染做优化, 没有使用 React.memo  useCallback 的情况下, 两个子组件任意一个点击, 都会使整个 MyApp 组件和所有子组件重新渲染, 增加了优化之后, 每次点击 MemoMyButton 都只会让 MyApp 和当前点击的子组件重新渲染.


用法2

    当传入 dependencies 后, 依赖的变化必然会导致函数缓存的更新, 有时这是不必要的, 也就是需要一种可以更新状态, 但不用更新函数缓存的方法, useCallback 同样具有这样的效果.

    在这个例子中, count 的变化, 始终会让 countClick 更新, 这同样会让 React.memo 失效, 显然 count 并不是一个合适的依赖项, 但是不传的话又会导致函数始终使用缓存中的状态, count 就会一直等于 1, 这种情况我们需要使用下面的写法.

    这样的写法可以让 useCallback 始终返回缓存中的函数, 同时也可以正确更新 count 的状态.

用法3

    useCallback 还可以配合 useEffect 使用,当 useEffect 的依赖是一个函数时,可以使用 useCallback 来缓存依赖函数,来避免 useEffect 不必要的执行

  不过这种方式并不推荐使用,一个函数的依赖项会很奇怪,而且完全可以不使用 useCallback 达到效果,像下面这样改写:

总结

  1. useCallback 是协助 React.memo 对子组件渲染优化的一个 hook;

  2. useCallback 需要谨慎使用, 传入合适的 dependencies 是优化的关键;

  3. useCallback 不应该用做功能, 只用来做优化;

  4. 不要在循环中直接使用 useCallback, 必要的话就写在循环的子组件中;

  5. 可以和 useEffect 一起使用,但是并不推荐;

  6. dependencies 不传会始终返回新函数, 传空数组会在渲染一次之后一直缓存;


React手册 Hooks 之 useCallback的评论 (共 条)

分享到微博请遵守国家法律