一、需求场景:父组件想要调用子组件的方法,状态
例:在图中,当我点击 修改按钮时,弹出编辑框。底层的列表为父组件,上面的弹出框为子组件
二、实现方法:
1.第一步:父组件中使用useRef定义ref,并绑定在子组件身上
//引入useRef函数
import {React,useEffect,useRef,useState} from 'react';
//定义ref
const editorRef=useRef()
//在子组件身上绑定
<Editor ref={editorRef}></Editor>
2.第二步(核心步骤):子组件中forwardRef+useImperativeHandle hook函数把方法暴露出去
核心api:
(1)forwardRef((props,ref) => {})
是React 中用于转发 ref
到子组件的函数。通过使用 forwardRef
,父组件可以获取子组件实例的引用,并直接操作子组件的 DOM 节点或调用子组件的方法。
(props, ref) => {}
是一个函数组件的定义,通过 forwardRef
包裹后,这个函数组件就具备了能够接收 ref
的能力。当父组件将 ref
传递给这个包裹后的函数组件时,父组件就可以访问到子组件的实例。
(2)useImperativeHandle(ref, createHandle, [deps])
有3个参数
ref
:对子组件暴露的引用,通常是通过useRef
创建的。createHandle
:一个函数,用来创建暴露给父组件的方法或属性。[deps]
:可选的依赖数组,类似于useEffect
中的依赖数组,当依赖数组中的值发生变化时,会重新创建暴露给父组件的方法或属性。
例:useImperativeHandle(ref, () => ({
show: (record) => {
setishow(true);
setformdata(record)
console.log(record)
},
}));
const Editor = forwardRef((props,ref) => {
const [formdata,setformdata]=useState({
name: '',
age: '',
address: ''})
const [ishow,setishow] = useState(false)
useImperativeHandle(ref, () => ({
show: (record) => {
setishow(true);
setformdata(record)
console.log(record)
},
}));
const handleOk=()=>{
}
const handleCancel=()=>{
setishow(false)
}
const onFinish = (values) => {
console.log('Success:', values);
};
const onFinishFailed = (errorInfo) => {
console.log('Failed:', errorInfo);
};
return(
<Modal
title="编辑"
open={ishow}
onOk={handleOk}
onCancel={handleCancel}
>
<Form
name="basic"
labelCol={{
span: 8,
}}
wrapperCol={{
span: 16,
}}
style={{
maxWidth: 600,
}}
initialValues={formdata}
onFinish={onFinish}
onFinishFailed={onFinishFailed}
autoComplete="off"
>
<Form.Item
label="姓名"
name="name"
rules={[
{
required: true,
message: 'Please input your username!',
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="年龄"
name="age"
rules={[
{
required: true,
message: 'Please input your username!',
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="地址"
name="address"
rules={[
{
required: true,
message: 'Please input your username!',
},
]}
>
<Input />
</Form.Item>
</Form>
</Modal>)
});
export default Editor;
3.父组件中调用子ref方法
editorRef.current.show(record) 还可以传递参数
const edit = (text, record) => {
editorRef.current.show(record)
};