useImperativeHandle 可以让你在使用 ref 时自定义暴露给父组件的实例值。在大多数情况下,应当避免使用 ref 这样的命令式代码。useImperativeHandle 应当与 forwardRef 一起使用。 如果只是获取子组件的某些属性、方法,则用useImperativeHandle就行,如果需要获取子组件中某些元素、组件实例、则必定需要forwardRef。
父、子组件在使用该hook时步骤如下:
- 父组件使用useRef(或createRef)创建一个ref对象,将这个ref对象赋给子组件的ref属性
-
子组件使用forwardRef包装自己,允许作为函数组件的自己使用ref。然后使用useImperativeHandle钩子函数,在该钩子函数的第二个函数参数中返回一些状态或方法,这个被返回的状态或方法就可以被父组件访问到。 - 父组件使用创建的ref对象的current属性获取子组件暴露出的状态或方法。
示例代码如下:
import React, { useRef, useImperativeHandle } from 'react';
import ReactDOM from 'react-dom';
const FancyInput = React.forwardRef((props, ref) => {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
}
}));
return <input ref={inputRef} type="text" />
});
const App = props => {
const fancyInputRef = useRef();
return (
<div>
<FancyInput ref={fancyInputRef} />
<button
onClick={() => fancyInputRef.current.focus()} // 调用子组件的方法
>父组件调用子组件的 focus</button>
</div>
)
}
ReactDOM.render(<App />, root);