ESLint提示在渲染阶段无法访问refs的错误,但我并没有在访问ref
我想把一个ref传给自定义函数,但在来自 eslint-plugin-react-hooks 的 react-hooks/refs 规则上,关于 dialog.ref 的部分收到了ESLint错误。我不太清楚为什么,因为我这里并没有访问 ref.current,只是把ref传给组件。出于某种原因,对hook返回值进行解构赋值可以正常工作,但我更倾向于 dialog.ref 的写法,因为我可能会有多个对话框(dialogA.ref,dialogB.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 */}
</>
)
}
解决方案
问题
当我把你的代码复制到一个项目中时,我看到一个不同的错误,且两种用例的表现并不完全相同。
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;
};
有了这个改动,两个用例看起来都能像预期那样正常工作。

