好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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

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}/>
?? ?)
}

子组件

import 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]{
? color: rgba(0, 0, 0, 0.85);
? background-color: transparent;
? cursor: default;
? border: unset;
? border-bottom: 1px solid #333;
}

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

查看更多关于React Hook父组件如何获取子组件的数据/函数的详细内容...

  阅读:42次