自定义useAsync React Hook如何在不触发重渲染时保持最新函数引用?
useAsync Hook 保持函数最新且不触发重渲染的原理
代码实现
import { useEffect, useRef, useState } from 'react' export function useAsync<T>( func: () => Promise<T> | undefined | null, deps = [], ) { const ref = useRef(func) ref.current = func const [value, setValue] = useState<T>() useEffect(() => { ref.current()?.then(setValue) // eslint-disable-next-line react-hooks/exhaustive-deps }, deps) return value }
问题
请解释该Hook在使用时,如何在不引发重渲染的情况下保持函数最新状态的原理。
原理拆解
1. 借助useRef的无重渲染特性
useRef创建的引用对象ref在组件整个生命周期内是同一个实例,它的.current属性更新不会触发组件重渲染——这是它和useState的核心区别,修改ref的current值完全不会干扰组件的渲染流程。
2. 实时同步最新函数引用
组件每次渲染时,都会执行ref.current = func,把外部传入的最新func函数赋值给ref.current。这个操作在每次组件渲染时都会执行,确保ref.current始终指向最新的函数,同时因为是修改ref,不会引发额外重渲染。
3. 精准控制useEffect的依赖范围
useEffect的依赖数组只传入业务相关的deps,没有把func加入依赖。这样只有当deps中的变量变化时,useEffect才会重新执行;而执行时调用的ref.current(),是已经同步好的最新函数引用。
这种写法既避免了因为func引用频繁变化(比如父组件每次渲染都创建新的匿名函数)导致useEffect反复触发、组件不必要重渲染的问题,又保证了每次useEffect执行时都能拿到最新的函数逻辑。
内容的提问来源于stack exchange,提问作者user29986340
相关产品推荐
相关产品推荐

