React Hook父组件如何获取子组件的数据/函数

2022-09-15 16:09:58

目录ReactHook父组件获取子组件数据/函数子组件MyWorldMap父组件MyTripReactHook父组件提交子组件form父组件子组件ReactHook父组件获取子组件数据/函数我们...

目录
React Hook父组件获取子组件数据/函数
子组件MyWorldMap
父组件MyTrip
React Hook父组件提交子组件form
父组件
子组件

React Hook父组件获取子组件数据/函数

我们知道在react中,常用props实现子组件数据到父组件的传递,但是父组件调用子组件的功能却不常用。

文档上说ref其实不是最佳的选择,但是想着偷懒不学redux,在网上找了很多教程,要不就是hook的讲的太少,要不就是父子组件傻傻分不清,于是只好再啃了一下文档,就学了一下其它hook的api。

在这里我们需要用到useImperativeHandle这个api,其函数形式为

useImperativeHandle(ref, createHandle, [deps])

其实这个api也是ref的一种形式,但是相当于做了一定的优化,可以选择让子组件只暴露一定的api给父组件,根据在文档和其他博客上给出的方法

一共有两大步骤:

1.将ref传递到子组件中
2.需要使用forwardRef对子组件进行包装

子组件MyWorldMap

const mapRef = useRef(null);
  useImperativeHandle(ref, () => {

    return {
      //clickSwitch是子组件暴露的函数
      clickSwitch() {
      
        if(type == 1){
          initChinaMap();
          setType(2);
        }else{
          initWordMap();
          setType(1);
        }
      
      }
    }
  })

//你的return内容,注意ref

  return(
    <React.Fragment>

      <div id={"myWorldMap"} style={{ width: "800px", height: "400px" }} ref={mapRef}></div>

    </React.Fragment>


  )
}


//最后要配合forwardRef
MyWorldMap = forwardRef(MyWorldMap);
export default MyWorldMap;

注:ref是子组件声明的时候传进来的,也就是

function MyWorldMap (props,ref){
//..你的代码
}

//export...

其实官方文档给出来的例子是:

function FancyInput(props, ref) {
 const inputRef = useRef();
 useImperativeHandle(ref, () => ({
  focus: () => {
   inputRef.current.focus();
  }
 }));
 return <input ref={inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);

两种方法都是可以的

父组件MyTrip

const myWordMapRef = useRef();

return(
 //省略一些代码,注意ref
<MyWorldMap proData = { myMapData} handleMapClick = {handleMapClick.bind(this)} ref={myWordMapRef}>

</MyWorldMap>
<div className={styles["mapButton-wrap"]}>
   <ButtonGroup>
       <Button onClick={() => myWordMapRef.current.clickSwitch()}>Switch</Button>
       <Button onClick={()=>clickAll() }>All</Button>
    </ButtonGroup>
</div>
)

现在你就可以在父组件里面通过myWordMapRef.current.clickSwitch()调用函数了

React Hook父组件提交子组件form

父组件

import React, { useState, useEffect, useRef } from 'react';
import { Button } from 'antd';
import EditClassA from './EditClassA';
export default (): React.ReactNode => {
 const [isEdit,setIsEdit] = useState<boolean>(false);
 const editClassARef = useRef();
 const handleSave = () => {
  // 调用子组件的方法
  editClassARef.current.changeVal();
 }
 return (
  <div>
   {!isEdit?(
    <Button style={{marginRight:20}} onClick={()=>setIsEdit(!isEdit)}>编辑</Button>
   ):(
    <Button style={{marginRight:20}} onClick={handleSave}>保存</Button>
   )}
  </div>
  <EditClassA isEdit={isEdit} setIsEdit={setIsEdit} ref={editClassARef}/>
 )
}

子组件

impopythonrt React, { useImperativeHandle, forwardRef } from 'react'编程;
import { Form , Input } from 'antd';
import style from '@/pages/BackEnd/style.less';
const EditClassA = forwardRef((props, ref) => {
 // props 里面有父组件的值和方法
 const [form] = Form.useForm();
 useImperativeHandle(ref, () => ({
  changeVal: () => {
   form
   .validateFields()
   .then( values => {
    // 调用父组件方法,设置父组件的值
    props.setIsEdit(!props.isEdit)
   })
   .catch(errorInfo => {
    return false
   })
  }
 }));
 return (
 <Form form={form} name="basic" colon={false} >
  <Form.Item
   label="总部名称"
   name="name"
   initialValue="总部"
   rules={[{required: true,message: '请输入总部名称',}]}>
   <Input className={props.isEdit?'':style.disabledInput} placeholder="请输入" disabled={!props.isEdit}/>
  </Form.Item>
 </Form>
 );
})
export default EditClassA
.disabledInput[disabled]{
www.cppcns.com color: rgba(0, 0, 0, 0.85);
 background-color: transparent;
 cursor: default;
 border: unset;
 border-bottom: 1px solid #333;
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。