ESLint提示在渲染阶段无法访问refs的错误,但我并没有在访问ref

前端开发 2026-07-10

我想把一个ref传给自定义函数,但在来自 eslint-plugin-react-hooksreact-hooks/refs 规则上,关于 dialog.ref 的部分收到了ESLint错误。我不太清楚为什么,因为我这里并没有访问 ref.current,只是把ref传给组件。出于某种原因,对hook返回值进行解构赋值可以正常工作,但我更倾向于 dialog.ref 的写法,因为我可能会有多个对话框(dialogA.refdialogB.ref)。

错误:在渲染期间无法访问refs

React refs是在渲染阶段不需要的值。Refs应该只在渲染之外访问,例如在事件处理程序或副作用中。在渲染期间访问引用值(current 属性)可能会导致组件无法按预期更新(https://react.dev/reference/react/useRef)。

Code:

export type DialogProps = ComponentPropsWithRef<"dialog">;

export function Dialog({ className = "", ...props }: DialogProps) {
  return (
    <dialog
      className={`ui-dialog ${className}`}
      {...props}
    />
  );
}
export type UseDialogReturnType = {
  ref: RefObject<HTMLDialogElement | null>;
  isOpen: boolean;
  handleOpen: () => void;
  handleClose: () => void;
};

export function useDialog(): UseDialogReturnType {
  const ref = useRef<HTMLDialogElement>(null);
  const [isOpen, setIsOpen] = useState<boolean>(false);

  const handleOpen = () => {
    if (ref.current) {
      ref.current.showModal();
      setIsOpen(true);
    }
  };

  const handleClose = () => {
    if (ref.current) {
      ref.current.close();
      setIsOpen(false);
    }
  };

  return {
    ref,
    isOpen,
    handleOpen,
    handleClose,
  };
}
export function MyComponent() {
  const dialog = useDialog();
  const { ref } = useDialog();

  return (
    <>
      <Dialog ref={dialog.ref} /> {/* Error: Cannot access refs during render */}
      <Dialog ref={ref} />        {/* This works for some reason */}
    </>
  )
}

解决方案

问题

当我把你的代码复制到一个项目中时,我看到一个不同的错误,且两种用例的表现并不完全相同。

IDE errors/issues

Type 'RefObject' is not assignable to type 'RefObject | ((instance: HTMLDialogElement | null) => void) | null | undefined'.

none Type 'RefObject<HTMLDialogElement | null>' is not assignable to type 'RefObject<HTMLDialogElement> | ((instance: HTMLDialogElement | null) => void) | null | undefined'. Type 'RefObject<HTMLDialogElement | null>' is not assignable to type 'RefObject<HTMLDialogElement>'. Type 'HTMLDialogElement | null' is not assignable to type 'HTMLDialogElement'. Type 'null' is not assignable to type 'HTMLDialogElement'.typescript(2322) index.d.ts(843, 61): The expected type comes from property 'ref' which is declared here on type 'IntrinsicAttributes & Omit<DetailedHTMLProps<DialogHTMLAttributes<HTMLDialogElement>, HTMLDialogElement>, "ref"> & { ...; }'

Dialog 组件中,ref 属性(由 ComponentPropsWithRef<"dialog"> 定义)是 RefObject<HTMLDialogElement> | ((instance: HTMLDialogElement | null) => void) | null | undefined

ref?:
  | ((instance: HTMLDialogElement | null) => void)
  | RefObject<HTMLDialogElement>
  | null
  | undefined

你的 useDialog 钩子返回一个 RefObject<HTMLDialogElement | null> 类型,这与之不兼容。

export type UseDialogReturnType = {
  ref: RefObject<HTMLDialogElement | null>; // <-- incompatible with component ref prop
  isOpen: boolean;
  handleOpen: () => void;
  handleClose: () => void;
};

解决方案建议

ref 属性定义在 UseDialogReturnType 中更新为 RefObject<HTMLDialogElement> | null

export type UseDialogReturnType = {
  ref: RefObject<HTMLDialogElement> | null;
  isOpen: boolean;
  handleOpen: () => void;
  handleClose: () => void;
};

有了这个改动,两个用例看起来都能像预期那样正常工作。

IDE without issues

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章