useImperativeHandle和ref转发
useImperativeHandle 可以让你在使用 ref 时自定义暴露给父组件的实例值,应当与 forwardRef 一起使用,实现ref转发
我们获取类组件实例后,可以直接调用实例上的方法!
import React, { useEffect, useRef} from "react";
class Child extends React.Component {
submit = () => {
console.log('调用了子组件的submit方法!');
};
render() {
return <div>
...
</div>;
}
}
export default function Demo() {
const box = useRef(null);
useEffect(() => {
console.log(box.current); //子组件的实例
box.current.submit();
}, []);
return <div>
<Child ref={box} />
</div>;
};
但是直接把 ref 赋值给函数组件,是不被允许的!
const Child = function () {
return <div>
...
</div>;
};
export default function Demo() {
const box = useRef(null);
useEffect(() => {
console.log(box.current); //null
// Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
}, []);
return <div>
<Child ref={box} />
</div>;
};
此时我们可以基于 forwardRef 和 useImperativeHandle , 就可以实现父组件调用子组件中的方法!
import React, { useEffect, useRef, useImperativeHandle, forwardRef } from "react";
const Child = forwardRef(function (props, ref) {
useImperativeHandle(ref, () => {
return {
submit: () => {
console.log('调用了子组件的submit方法!');
}
};
});
return <div>
...
</div>;
});
export default function Demo() {
const box = useRef(null);
useEffect(() => {
console.log(box.current);
box.current.submit();
}, []);
return <div>
<Child ref={box} />
</div>;
};