我需要从父组件内的自定义子组件调用方法。
但不幸的是,子组件(称为 CanvasUI)的引用始终为空。我不明白为什么,因为在我看来,我已经正确地实现了一切。
这是我的父组件
...
export default function Home() {
...
const canvas = useRef<CanvasRef>(null);
...
function clearCanvas() {
// canvas.current.resetCanvas();
console.log(canvas.current);
}
return (
<div className="flex justify-center items-center min-h-screen min-w-screen bg-main">
<div className="flex flex-col">
...
<div className="flex justify-center">
...
<CanvasUI disabled={disableCanvas} word={activeWord} ref={canvas} />
...
</div>
...
<button onClick={() => clearCanvas()}>clear canvas</button>
</div>
</div>
);
}
这是 CanvasUI 组件
...
export default function CanvasUI({
disabled,
word,
ref,
}: {
disabled: boolean;
word: string;
ref: Ref<CanvasRef>;
}) {
...
useImperativeHandle(ref, () => ({ getCanvas, loadCanvas, resetCanvas }));
...
function resetCanvas(): void {
...
}
...
function getCanvas(): String {
...
}
function loadCanvas(data: String, immediate: Boolean): void {
...
}
return (
...
);
}
CanvasRef 接口
export default interface CanvasRef {
getCanvas: () => String;
loadCanvas: (data: String, immediate: Boolean) => void;
resetCanvas: () => void;
}
我省略了不重要的代码以使其更具可读性
您不能将
ref
用作组件中的 prop,因为它是保留的 1 2 3(就像 key
)。当调用函数组件时,React 将省略 ref
中的 props
属性。
相反,您应该将
ref
作为 CanvasUI
组件的第二个参数,然后使用 forwardRef
创建它。 useImperativeHandle
的文档对此进行了解释:
使用命令句柄
useImperativeHandle(ref, createHandle, [deps])
自定义使用useImperativeHandle
时暴露给父组件的实例值。与往常一样,在大多数情况下应避免使用引用的命令式代码。ref
应与useImperativeHandle
一起使用:forwardRef
function FancyInput(props, ref) { const inputRef = useRef(); useImperativeHandle(ref, () => ({ focus: () => { inputRef.current.focus(); } })); return <input ref={inputRef} ... />; } FancyInput = forwardRef(FancyInput);
在此示例中,呈现
的父组件将能够调用<FancyInput ref={inputRef} />
。inputRef.current.focus()