You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中传递自定义Hook返回的ref触发ESLint 'Cannot access refs during render'报错的问题排查

我来帮你拆解这个问题哈~

为啥会出现这个ESLint报错?

其实这是react-hooks/refs规则的误报。这条规则本来是用来阻止你在组件渲染阶段直接访问ref.current的——毕竟current的值在渲染期间可能还没更新,用它来渲染UI会导致页面状态不一致。但你这里只是把ref对象本身传递给组件,根本没碰current属性,这种用法其实完全安全。

那为啥解构的写法没问题?这是因为ESLint的检测逻辑有点“死板”:当你用dialog.ref这种方式从Hook返回的对象里取ref时,它会直接触发警告;但你用解构const { ref } = useDialog()时,规则没把这个变量和“不安全的ref访问”关联起来,所以就放过了。

怎么解决这个问题?

给你几个适配你需求的方案:

1. 直接禁用该行的ESLint规则

既然你确认这个用法是安全的,最直接的办法就是在报错的那行加个注释跳过检测:

<Dialog ref={dialog.ref} /> {/* eslint-disable-next-line react-hooks/refs */}

2. 用中间变量暂存ref

有时候把dialog.ref赋值给一个中间变量,就能绕过ESLint的检测逻辑,写法也很简单:

export function MyComponent() {
  const dialog = useDialog();
  const dialogRef = dialog.ref; // 先把ref存到中间变量里
  return (
    <>
      <Dialog ref={dialogRef} /> {/* 这样就不会报错啦 */}
    </>
  )
}

3. 修复Dialog组件的ref转发(重要!)

另外得提醒你一个容易忽略的点:你的Dialog组件现在根本没正确转发ref!你用了ComponentPropsWithRef<"dialog">但没配合forwardRef,导致你传递给Dialog的ref会被当成普通props,根本绑不到内部的原生<dialog>元素上。得改成这样:

import { forwardRef, ComponentPropsWithoutRef } from 'react';

export type DialogProps = ComponentPropsWithoutRef<"dialog">;
export const Dialog = forwardRef<HTMLDialogElement, DialogProps>(({ className = "", ...props }, ref) => {
  return (
    <dialog ref={ref} className={`ui-dialog ${className}`} {...props} />
  );
});
// 别忘了加displayName,不然React DevTools里会显示成ForwardRef,调试起来很麻烦
Dialog.displayName = "Dialog";

改完之后,useDialog里的ref.current才能真正拿到原生的dialog DOM节点,你写的handleOpen、handleClose才能正常工作。

最后补充一句

虽然这个规则偶尔会误报,但它大部分时候还是很有用的——能帮你避免在渲染阶段依赖ref.current的值(比如用它来计算UI),毕竟ref更新不会触发组件重渲染,很容易导致UI和实际状态脱节。但仅仅传递ref对象本身是完全安全的,所以遇到这种误报时,直接禁用单条规则是完全合理的选择~

内容的提问来源于stack exchange,提问作者Joe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 06:38:56