Yasin

Yasin

解决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 负责同步