多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
[TOC] ## 概述 useCallback 是一个允许你在多次渲染中缓存函数的 React Hook。 **默认情况下,当一个组件重新渲染时, React 将递归渲染它的所有子组件** 语法 ``` useCallback(fn, dependencies) ``` ## 示例 ### Hello World bad ``` function ProductPage({ productId, referrer, theme }) { // 每当 theme 改变时,都会生成一个不同的函数 function handleSubmit(orderDetails) { post('/product/' + productId + '/buy', { referrer, orderDetails, }); } return ( <div className={theme}> {/* 这将导致 ShippingForm props 永远都不会是相同的,并且每次它都会重新渲染 */} <ShippingForm onSubmit={handleSubmit} /> </div> ); } ``` good ``` function ProductPage({ productId, referrer, theme }) { // 在多次渲染中缓存函数 const handleSubmit = useCallback((orderDetails) => { post('/product/' + productId + '/buy', { referrer, orderDetails, }); }, [productId, referrer]); // 只要这些依赖没有改变 return ( <div className={theme}> {/* ShippingForm 就会收到同样的 props 并且跳过重新渲染 */} <ShippingForm onSubmit={handleSubmit} /> </div> ); } ``` ## useCallback 与 useMemo 有何关系? ``` import { useMemo, useCallback } from 'react'; function ProductPage({ productId, referrer }) { const product = useData('/product/' + productId); const requirements = useMemo(() => { //调用函数并缓存结果 return computeRequirements(product); }, [product]); const handleSubmit = useCallback((orderDetails) => { // 缓存函数本身 post('/product/' + productId + '/buy', { referrer, orderDetails, }); }, [productId, referrer]); return ( <div className={theme}> <ShippingForm requirements={requirements} onSubmit={handleSubmit} /> </div> ); } ``` * **[`useMemo`](https://zh-hans.react.dev/reference/react/useMemo)缓存函数调用的结果**。在这里,它缓存了调用`computeRequirements(product)`的结果。除非`product`发生改变,否则它将不会发生变化。这让你向下传递`requirements`时而无需不必要地重新渲染`ShippingForm`。必要时,React 将会调用传入的函数重新计算结果。 * **`useCallback`缓存函数本身**。不像`useMemo`,它不会调用你传入的函数。相反,它缓存此函数。从而除非`productId`或`referrer`发生改变,`handleSubmit`自己将不会发生改变。这让你向下传递`handleSubmit`函数而无需不必要地重新渲染`ShippingForm`。直至用户提交表单,你的代码都将不会运行。