解决error cannot access refs during render问题
这个错误出现在渲染期间直接读写 ref,而 ref 只能在副作用或事件处理器中访问。
常见触发场景及解法
1. 渲染时直接读取 ref.current
// ❌ 错误:render 期间访问
function Comp() {
const ref = useRef(null);
const height = ref.current?.clientHeight; // render 时 current 还是 null
return <div ref={ref} style={{ marginTop: height }} />;
}
// ✅ 正确:用 state 存储,在 effect 中更新
function Comp() {
const ref = useRef(null);
const [height, setHeight] = useState(0);
useEffect(() => {
setHeight(ref.current?.clientHeight ?? 0);
}, []);
return <div ref={ref} style={{ marginTop: height }} />;
}
2. 渲染时调用了修改 ref 的函数
// ❌ 错误
function Comp() {
const ref = useRef(null);
scrollToBottom(ref); // 直接在 render 里调用
return <div ref={ref} />;
}
// ✅ 正确:放进 useEffect 或事件处理器
useEffect(() => {
scrollToBottom(ref);
}, [dependency]);
3. React 19 新增限制:渲染期间不能访问其他组件的 ref
// ❌ React 19 报错:父组件 render 时访问子组件 ref
function Parent() {
const childRef = useRef(null);
const width = childRef.current?.offsetWidth; // 报错
return <Child ref={childRef} />;
}
// ✅ 用 callback ref + state
function Parent() {
const [width, setWidth] = useState(0);
return <Child ref={(el) => setWidth(el?.offsetWidth ?? 0)} />;
}
核心原则
- render 是纯函数,只能读 props/state,不能有副作用
- ref 的读写 → 放进
useEffect/useLayoutEffect/ 事件处理器 - 需要在渲染中用的值 → 先存进
state,由 effect 负责同步
