React v19下如何实现不渲染时访问ref.current的usePrevious Hook?
React v19 下 usePrevious Hook 的正确实现方式
我之前用以下代码实现usePrevious Hook:
import { useEffect, useRef } from 'react'; export const usePrevious = (value: unknown) => { const ref = useRef<unknown>(); useEffect(() => { ref.current = value; }); return ref.current; };
升级至React v19后,触发ESLint报错:
Ref values (the
currentproperty) may not be accessed during render. (eslint(react-compiler/react-compiler))
报错原因
React v19的编译器严格禁止在渲染阶段访问ref的current属性。ref是可变容器,直接在渲染阶段读取会导致渲染结果依赖可变状态,破坏渲染的可预测性与纯函数特性。原实现中return ref.current属于在渲染阶段读取可变ref值,因此触发报错。
正确实现方式
以下两种实现均符合React v19编译器要求:
方式一:使用单个ref保存当前与历史值
import { useRef } from 'react'; export function usePrevious<T>(value: T): T | undefined { const ref = useRef<{ current: T | undefined; previous: T | undefined }>({ current: undefined, previous: undefined, }); if (ref.current.current !== value) { ref.current.previous = ref.current.current; ref.current.current = value; } return ref.current.previous; }
方式二:使用两个独立ref
import { useRef } from 'react'; export function usePrevious<T>(value: T): T | undefined { const previousRef = useRef<T>(); const currentRef = useRef<T>(); if (currentRef.current !== value) { previousRef.current = currentRef.current; currentRef.current = value; } return previousRef.current; }
实现说明
两种实现均在渲染阶段完成值的更新逻辑,避免了在渲染阶段读取可变ref的current属性作为返回值,同时保证返回的是上一次传入的value值,完全适配React v19的编译器规则。
内容的提问来源于stack exchange,提问作者Frank Fiegel
相关产品推荐
相关产品推荐

