React中useRef的用途及两段示例代码相关问题解答
useRef 常见用法问题解答
前置基础:useRef是React提供的用于存储跨渲染周期可变值的Hook,核心特性有两个:一是修改.current属性上存储的值不会触发组件重渲染;二是组件从首次挂载到卸载的全生命周期内,ref对象的引用保持稳定,存储的值不会因为重渲染被重置。
1. useRef(true) 和 useRef(false) 的区别
两者唯一的差异是ref对象的初始值不同:
useRef(true)初始化时,ref对象的.current属性初始值为布尔值trueuseRef(false)初始化时,ref对象的.current属性初始值为布尔值false
初始值仅在组件首次渲染时生效,后续组件重渲染不会重复执行初始化逻辑重置ref值,你可以在任意时机直接修改.current属性更新存储的内容。
2. 两段示例代码的含义
代码1:自定义挂载状态Hook useIsMountedRef
export default function useIsMountedRef() { const isMounted = useRef(true); useEffect( () => () => { isMounted.current = false; }, [] ); return isMounted; }
这是React开发中非常通用的工具自定义Hook,作用是实时标记组件的挂载状态,解决「组件卸载后异步回调内调用setState触发React警告」的经典问题:
- 初始化ref时赋值
true:组件首次渲染执行到这行代码时,已经处于挂载完成状态,因此直接标记为已挂载 - 传入空依赖数组的
useEffect,其返回的清理函数仅会在组件卸载时执行,执行时将isMounted.current改为false,标记组件已卸载 - 最终将ref返回给业务组件使用,业务侧可以在异步请求、定时器回调中先判断
isMounted.current是否为true,再执行状态更新逻辑,避免卸载后操作组件的报错。
代码2:跳过首次执行的依赖监听逻辑
const mounted = useRef(false); useEffect(() => { if (!mounted.current) { mounted.current = true; } else { // 业务逻辑代码 } }, [dependency]);
这段代码的作用是让useEffect内的业务逻辑仅在依赖项更新触发重渲染时执行,跳过组件首次挂载时的默认执行:
- 初始化ref时赋值
false,用来标记「是否已经完成首次effect执行」 - useEffect监听目标依赖
dependency:- 组件首次挂载、effect第一次运行时,
mounted.current为初始值false,仅将标记改为true,不执行业务代码 - 后续每次
dependency变化触发effect重新执行时,mounted.current已经为true,就会进入else分支运行实际业务逻辑。
- 组件首次挂载、effect第一次运行时,
3. useEffect中使用useRef的核心作用
- 实现跨渲染周期的稳定值存储:普通函数内定义的变量会在每次组件重渲染时重置,无法跨渲染周期保留标记值;如果用
useState存储这类标记,修改值会触发不必要的组件重渲染,useRef刚好规避这两个问题。 - 避免effect意外重复执行:ref对象本身的引用在组件全生命周期保持稳定,不会因为组件重渲染生成新的引用,不会导致useEffect因为依赖项引用变化意外触发执行,非常适合存储不需要参与视图渲染的标记位。
- 规避闭包陈旧值问题:ref的
.current属性始终存储最新值,不会出现useEffect闭包捕获到旧渲染周期变量值的问题,能保证逻辑执行时拿到的状态是最新的。
内容的提问来源于stack exchange,提问作者yoyoyoyo
相关产品推荐
相关产品推荐

