React Hooks引入了一种全新的方式来处理state和其他React特性,让我们可以以更加声明式的风格去编写代码,从而使代码更加易读和可维护。其中,**useCallback
是一个常被提及但可能被大家误解或未能充分利用的hook。useCallback
**为我们提供了避免不必要渲染以及记住函数实例的能力,从而在性能优化上给我们开发者带来了新的手段。
useCallback
简单来说,useCallback
是一种能让你创建记住某函数的方法,该函数只在其依赖性发生改变时更新。
javascriptconst memoizedCallback = useCallback( () => { doSomething(a, b); }, [a, b], );
即使我们在多次重新渲染中调用 useCallback
,只要 a
和 b
这两个依赖项不发生变化,那么 useCallback
将继续返回我们上一次定义的 doSomething
的同一个实例。
useCallback
作用为了给大家进一步说明 useCallback
的作用,让我们来看一个实际例子:
javascriptfunction 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可能你已经阅读了关于 useEffect
,useMemo
等其他Hook的教程,所以,让我们来看看它们与 useCallback
有何不同。
useEffect
是用来处理副作用的,包括网络请求,DOM操作等。useMemo
是用来记忆复杂计算结果的,以使其在依赖性不变的前提下,在不同渲染中被重复使用。useCallback
与 useMemo
在本质上类似,不过 useCallback
记住的是函数,而 useMemo
记住的是计算结果。适当条件下的传给子组件的函数
如果你正在将函数作为 prop 传递给子组件,并且该子组件是一个 PureComponent
(也就是说该子组件只有在 props 变化时才会重新渲染),那么 useCallback
就明显有用了。在这种情况下,如果你没有使用 useCallback
,那么每次父组件的函数重新渲染,都会导致子组件也跟着重新渲染,从而影响应用的性能。
避免过度使用
虽然 useCallback
可以帮助我们避免不必要的重新渲染和函数实例的重新创建,但如果过度使用,反而可能会导致性能问题。每次使用 useCallback
,我们都会创建一个新的函数和一个新的依赖数组,这都是有开销的。因此,对于不那么频繁触发的事件处理器或者低开销的函数来说,过度使用 useCallback
反而可能会增加总的资源消耗。
这篇文章希望能帮助你理解在什么时候以及如何使用React Hook—— useCallback
。总的来说,useCallback
是一个非常有用的工具,它可以帮助我们优化性能,避免不必要的重新渲染,并使代码更加可读。