首先,我们需要定义一个接口来描述我们希望暴露给父组件的方法。然后,在 useImperativeHandle 中实现这些方法,并确保它们符合这个接口。
TypeScript 示例代码
import React, { useRef, useImperativeHandle, forwardRef, MutableRefObject } from 'react';
// 定义一个接口来描述我们希望暴露给父组件的方法
interface ChildComponentHandles {
focus: () => void;
}
// 子组件接收 ref 并使用 useImperativeHandle 来自定义暴露的方法
const ChildComponent = forwardRef<ChildComponentHandles, {}>((props, ref) => {
const inputRef = useRef<HTMLInputElement>(null);
// 使用 useImperativeHandle 自定义 ref 的 current 属性
useImperativeHandle(ref, () => ({
focus() {
if (inputRef.current) {
inputRef.current.focus();
}
},
// 可以添加更多的方法
}));
return <input ref={inputRef} />;
});
// 父组件通过 ref 调用子组件中定义的方法
const ParentComponent: React.FC = () => {
const childRef = useRef<ChildComponentHandles>(null);
const handleClick = () => {
// 现在可以通过 childRef 调用 ChildComponent 中定义的 focus 方法
if (childRef.current) {
childRef.current.focus();
}
};
return (
<>
{/* 将 ref 传递给子组件 */}
<ChildComponent ref={childRef} />
<button onClick={handleClick}>Focus Input</button>
</>
);
};
export default ParentComponent;
关键点解释
-
接口定义:
- 我们定义了一个名为
ChildComponentHandles的接口,它规定了focus方法的签名。
- 我们定义了一个名为
-
forwardRef和泛型参数:- 在
forwardRef中,我们使用了两个泛型参数:第一个是ChildComponentHandles,表示我们将要暴露给父组件的方法集合;第二个是{},代表组件的 props 类型(在这个例子中没有使用任何额外的 props)。
- 在
-
useImperativeHandle:- 我们使用
useImperativeHandle来指定当父组件访问childRef.current时返回的对象应该包含哪些方法。这里我们实现了focus方法,该方法调用了内部inputRef的focus方法。
- 我们使用
-
useRef和类型注解:- 在
ParentComponent中,我们使用useRef<ChildComponentHandles>(null)来创建一个带有特定类型的ref,这样 TypeScript 就知道childRef.current应该有哪些属性和方法。
- 在
-
安全检查:
- 在调用
focus方法之前,我们进行了空值检查 (if (childRef.current)) 以避免可能的运行时错误。
- 在调用
这段代码展示了如何在 TypeScript 中正确地使用 forwardRef 和 useImperativeHandle 来控制从子组件到父组件的交互方式,同时保持了良好的类型安全性和可读性。
前端工程师、程序员

浙公网安备 33010602011771号