React 内置 Hook 之 useCallback 深度解析与使用案例

前言

React Hooks引入了一种全新的方式来处理state和其他React特性,让我们可以以更加声明式的风格去编写代码,从而使代码更加易读和可维护。其中,**useCallback是一个常被提及但可能被大家误解或未能充分利用的hook。useCallback**为我们提供了避免不必要渲染以及记住函数实例的能力,从而在性能优化上给我们开发者带来了新的手段。

什么是 useCallback

简单来说,useCallback是一种能让你创建记住某函数的方法,该函数只在其依赖性发生改变时更新。

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

即使我们在多次重新渲染中调用 useCallback,只要 ab这两个依赖项不发生变化,那么 useCallback将继续返回我们上一次定义的 doSomething的同一个实例。

useCallback 作用

为了给大家进一步说明 useCallback的作用,让我们来看一个实际例子:

javascript
function ParentComponent() { const [inputValue, setInputValue] = useState(''); const handleChange = useCallback((event) => { setInputValue(event.target.value); }, []); return ( <div> <input type="text" value={inputValue} onChange={handleChange} /> <ChildComponent handleChange={handleChange} /> </div> ); }

在这个例子中,我们将 handleChange回调函数(这是一个带有可记忆版本的函数)作为一个prop传递给子组件。如果我们未使用 useCallback,每次从父级重新渲染中父级组件都会生成 handleChange的新版本,导致子组件无意义的重新渲染。

然后,因为我们使用了 useCallback,子组件接收到的 handleChange prop变成一个稳定的版本并且只在依赖项改变时被更新,这阻止了子组件的无意义渲染。

useCallback vs 其他Hooks

可能你已经阅读了关于 useEffectuseMemo等其他Hook的教程,所以,让我们来看看它们与 useCallback有何不同。

  1. useEffect是用来处理副作用的,包括网络请求,DOM操作等。
  2. useMemo是用来记忆复杂计算结果的,以使其在依赖性不变的前提下,在不同渲染中被重复使用。
  3. useCallbackuseMemo在本质上类似,不过 useCallback记住的是函数,而 useMemo记住的是计算结果。

使用建议

  1. 适当条件下的传给子组件的函数

    如果你正在将函数作为 prop 传递给子组件,并且该子组件是一个 PureComponent(也就是说该子组件只有在 props 变化时才会重新渲染),那么 useCallback 就明显有用了。在这种情况下,如果你没有使用 useCallback,那么每次父组件的函数重新渲染,都会导致子组件也跟着重新渲染,从而影响应用的性能。

  2. 避免过度使用

    虽然 useCallback 可以帮助我们避免不必要的重新渲染和函数实例的重新创建,但如果过度使用,反而可能会导致性能问题。每次使用 useCallback,我们都会创建一个新的函数和一个新的依赖数组,这都是有开销的。因此,对于不那么频繁触发的事件处理器或者低开销的函数来说,过度使用 useCallback 反而可能会增加总的资源消耗。

总结

这篇文章希望能帮助你理解在什么时候以及如何使用React Hook—— useCallback。总的来说,useCallback是一个非常有用的工具,它可以帮助我们优化性能,避免不必要的重新渲染,并使代码更加可读。