学网站开发的培训学校,网站地图制作视频教程,wordpress页面链接404错误,网站案例介绍useMemoizedFn文档地址#xff1a;https://ahooks.js.org/zh-CN/hooks/use-memoized-fn
hooks组件内什么时候会更新自定义函数
在 React 中#xff0c;自定义的 Hooks 内部的函数在以下常见的几种情况下会被重新赋值#xff0c;导致更新引用#xff1a; 组件重新渲染https://ahooks.js.org/zh-CN/hooks/use-memoized-fn
hooks组件内什么时候会更新自定义函数
在 React 中自定义的 Hooks 内部的函数在以下常见的几种情况下会被重新赋值导致更新引用 组件重新渲染 当组件重新渲染时Hooks 内部的函数会被重新执行从而导致函数的重新赋值和更新引用。 这意味着每次组件重新渲染时Hooks 内部的函数会被重新计算返回新的函数引用。 依赖项发生变化对于使用了依赖项的 Hooks 对于某些 Hooks例如 useEffect、useMemo 和 useCallback当其依赖项发生变化时Hooks 内部的函数也会被重新执行。 这会导致函数的重新赋值和更新引用以确保在依赖项发生变化时能够获得最新的函数引用。 闭包内部依赖的状态发生变化 自定义的 Hooks 可能使用闭包内部的状态或其他上下文中的值作为依赖如果这些依赖的状态发生变化Hooks 内部的函数也会重新执行。这样做是为了保持函数内部依赖的状态是最新的避免出现闭包中使用过期数据的问题。
useCallback和useMemoizedFn对比
在 React 中useMemoizedFn 和 useCallback 都用于优化函数组件的性能但它们有一些不同点。
目的: useMemoizedFn: 这不是 React 的内置 Hook而是可能由第三方库提供的功能。它的目的是将一个函数 “记忆化”类似于 useCallback但在某些情况下它提供了更多的功能例如支持自定义的缓存策略和多个实例之间共享缓存等。useCallback: 这是 React 的内置 Hook专门用于记忆化函数。它的主要目的是在依赖项列表不变时返回相同的函数引用以减少函数的重新创建。 用法: useMemoizedFn 的基本思想是将一个函数包装起来并根据特定的条件缓存函数的结果以便在相同的输入参数下再次调用时直接返回缓存的结果而不必重新计算。useCallback 接受一个函数和依赖项列表并在依赖项列表不变时返回记忆化的函数引用。
import React, { useState, useCallback } from react;
import { message } from antd;
import { useMemoizedFn } from ahooks;export default () {const [count, setCount] useState(0);const callbackFn useCallback(() {message.info(Current count is ${count});}, [count]);const memoizedFn useMemoizedFn(() {message.info(Current count is ${count});});return (pcount: {count}/pbuttontypebuttononClick{() {setCount((c) c 1);}}Add Count/buttondiv style{{ marginTop: 16 }}button typebutton onClick{callbackFn}call callbackFn/buttonbutton typebutton onClick{memoizedFn} style{{ marginLeft: 8 }}call memoizedFn/button/div/);
};在上面的示例中callbackFn和memoizedFn效果是一样的区别在于memoizedFn不用自己指定依赖。
useCallback使用useMemo实现
使用 useMemo 来实现类似于 useCallback 的功能。事实上useCallback 本质上就是使用 useMemo 来进行函数记忆化的一种简化形式。
useCallback 和 useMemo 都是 React 的内置 Hook它们都用于在依赖项不变时返回记忆化的值。唯一的区别是 useCallback 是专门用于记忆化函数而 useMemo 可以用于任何类型的值。
在 React 组件中当函数作为依赖项传递给子组件时通常会使用 useCallback 来确保子组件不会因为父组件的重新渲染而频繁地创建新的函数。然而你也可以使用 useMemo 来达到相同的目的。
下面是一个使用 useMemo 实现类似于 useCallback 的示例
import React, { useState, useMemo } from react;function useMyCallback(callback, deps) {return useMemo(() callback, deps);
}const MyComponent () {const [count, setCount] useState(0);// 使用 useMyCallback 记忆化函数const handleClick useMyCallback(() {console.log(Callback function called);setCount(count 1);}, [count]);return (divpCount: {count}/pbutton onClick{handleClick}Increment/button/div);
};
在上面的示例中我们定义了一个 useMyCallback Hook它接受一个函数 callback 和一个依赖项列表 deps。在内部我们使用 useMemo 将传入的 callback 进行记忆化并返回记忆化的函数引用。
这样当 count 不变时handleClick 将返回相同的函数引用避免了因为父组件重新渲染而导致的函数的频繁创建从而实现了和 useCallback 类似的功能。
useMemoizedFn使用useMemo实现
useMemoizedFn 是持久化 function 的 Hook理论上可以使用 useMemoizedFn 完全代替 useCallback。使用 useMemoizedFn可以省略第二个参数 deps同时保证函数地址永远不会变化。
function useMemoizedFn(func){if(typeof func ! function) return// 通过 useRef 保持其引用地址不变并且值能够保持值最新const funcRef useRef(func)funcRef.current useMemo((){return func}, [func])const memoizedFn useRef();if (!memoizedFn.current) {// 返回的持久化函数调用该函数的时候调用原始的函数memoizedFn.current function(...args){return funcRef.current.apply(this, args)}}return memoizedFn.current
}ahooks源码实现如下
import { useMemo, useRef } from react;
import { isFunction } from ../utils;
import isDev from ../utils/isDev;
function useMemoizedFn(fn) {if (isDev) {if (!isFunction(fn)) {console.error(useMemoizedFn expected parameter is a function, got .concat(typeof fn));}}var fnRef useRef(fn);// why not write fnRef.current fn?// https://github.com/alibaba/hooks/issues/728fnRef.current useMemo(function () {return fn;}, [fn]);var memoizedFn useRef();if (!memoizedFn.current) {memoizedFn.current function () {var args [];for (var _i 0; _i arguments.length; _i) {args[_i] arguments[_i];}return fnRef.current.apply(this, args);};}return memoizedFn.current;
}
export default useMemoizedFn;useMemoizedFn 的实现中使用了两个 useRef 钩子具有不同的用途 fnRef这个 useRef 用于存储原始函数fn的引用。它被初始化为传递给 useMemoizedFn 函数的 fn 参数并且其目的是始终保持函数的最新版本。使用它的原因是确保记忆化的函数memoizedFn能够始终调用最新版本的原始函数 fn即使在渲染之间 fn 发生了变化。 memoizedFn这个 useRef 用于存储将由 useMemoizedFn 钩子返回的记忆化函数。其目的是在渲染间保持记忆化函数的引用。当 memoizedFn 首次创建时它被赋值为一个新的函数该函数调用最新版本的 fnRef.current 并传递提供的参数。然后这个记忆化函数被返回并在组件中使用。
这样的实现通过使用两个独立的 useRef 钩子确保记忆化函数能够正确地引用最新版本的原始函数同时保持记忆化函数本身的稳定引用。
使用 useMemo 更新 fnRef.current 而不是直接赋值 fnRef.current fn是为了确保当 fn 依赖项发生变化时记忆化函数会被重新计算。通过在 useMemo 中使用 [fn] 作为依赖项数组记忆化函数将始终引用 fn 的最新版本并在 fn 发生变化时相应地更新。
这个实现旨在确保 useMemoizedFn 返回的记忆化函数保持高效并正确地反映原始函数的最新版本和其依赖项的最新变化。
参考文章
https://juejin.cn/post/7106061970184339464#heading-6
https://ahooks.js.org/zh-CN/hooks/use-memoized-fn