帮同事debug发现的问题,记录一下,
弗曼学习大法好

interface RefFunType {hdlUpdate(): void,name: string
}

父组件使用useRef

useRef<RefFunType>()

传入的泛型是子组件存放在ref.current中的数据格式,
(如果子组件内部绑定了自己的ref,那用的泛型为useRef

ref是绑定在自定义组件上,子组件直接从props中获取ref是获取不到的,
这是因为ref不是prop属性,会像key一样,被React进行特殊处理

所以需要使用

React.forwardRef((props: any, React.Ref<unknown> | undefined) => {...})

将ref再重新转发到子组件中

在子组件中使用useImperativeHandle

useImperativeHandle(ref, () => ({[key:string]: any
}));

第一个param为转发的ref,第二个参数为一个fun,返回一个对象,这个对象就是可以在父组件中通过ref.current?.XXX获取到的方法和数据

在父组件中,需要注意的是,ref 对象内容发生变化时,useRef 并不会通知你,当.current改变时,组件并不会rerender。

因此,当我们需要在父组件中使用子组件的数据时,有两种方法。

  • 一种是在useEffect中将ref.current.XXX存放到state中,因为useEffect的调用是在组件完成渲染之后,也就是didMount之后才会调用,这个时候子组件已经渲染完成,内部的数据也已经构建完成,所以可以获取到内部数据
useEffect(() => {setName(childRef.current!.name)
})
  • 另外一种是使用回调ref,使用一个回调函数代替useRef
    (官方:使用 callback ref 可以确保 即便子组件延迟显示被测量的节点 (比如为了响应一次点击),我们依然能够在父组件接收到相关的信息,以便更新测量结果。)
const sexRef = useCallback(node => {console.log('node && node.name', node && node.name)node && setSex(node.name);
}, []);<SexChild ref={sexRef}></SexChild>

而需要在父组件中调用子组件的方法的时候,我们可以使用这种方法

<button onClick={() => childRef.current?.hdlUpdate()}>update</button>

将子组件的方法嵌套多一层方法,如果不创建一个自己的方法的话,在第一次render的时候,current中的方法还没有创建完成,所以我们会将undefined传递给onClick。
而当我们创建了一个自己的方法,在内部去调用current.hdlUpdate的时候,此时调用的是current这个引用上的方法(把ref看成一个不会通知组件render,也不会重新创建的对象),此时hdlUpdate方法已经存在了。

一个比较具体的例子:

interface RefFunType {hdlUpdate(): void,name: string
}// 子组件,使用forwardRef转发
const NameChild = forwardRef((props: any, ref: React.Ref<unknown> | undefined) => {const [name, setName] = useState('jack');useImperativeHandle(ref,// 将需要的方法暴露出去() => ({hdlUpdate: () => {console.log('name', name)},name: 'name'}))return <>name: <input value={name} onChange={e => setName(e.target.value)}></input></>
});// 另一个一样的子组件
const SexChild = forwardRef((props: any, ref: React.Ref<unknown> | undefined) => {const [sex, setSex] = useState('man');useImperativeHandle(ref,() => ({hdlUpdate: () => {console.log('sex', sex)},name: sex}))return <>sex: <input value={sex} onChange={e => setSex(e.target.value)}></input></>
})interface SwitchComponentProps {Component: React.ReactNode
}
// 中间组件,用来测试每次调用的current是否是当前子组件的,和直接在父组件写if渲染一样
const SwitchComponent:FC<SwitchComponentProps> = ({Component}) => {return <div>{Component}</div>
}// 父组件
const Index: FC = (props) => {const [type, setType] = useState(0);const [name, setName] = useState("");// 创建refconst childRef = useRef<RefFunType>();const childrens = [{ component: <NameChild ref={childRef} /> },{ component: <SexChild ref={childRef} /> }];// 获取数据useEffect(() => {setName(childRef.current!.name)})// console.log('childRef.current', childRef.current)// const timer = setInterval(() => {//     console.log('childRef.current', childRef.current)// }, 3000)// 在onClick绑定自己的方法,调用方法return <div>{name}<SwitchComponent Component={childrens[type].component}/><button onClick={() => type ? setType(0) : setType(1)}>switch type</button><button onClick={() => childRef.current?.hdlUpdate()}>update</button></div>
}

这个是官方父组件调用子组件中的input的focus方法的例子

const FancyInput = forwardRef((props: any, ref: React.Ref<unknown> | undefined) => {const inputRef = useRef<HTMLInputElement>(null);useImperativeHandle(ref, () => ({focus: () => {inputRef.current?.focus();}}));return <input ref={inputRef} />;
})

React 父组件获取子组件的方法/数据(useRef相关推荐

  1. jquery查找父窗体id_Vue父组件获取子组件中的变量

    全世界只有不到3 % 的人关注了我 你真是个特别的人 在vue项目日常开发中,难免要把功能性组件抽离出来,这样结构就会出现父子组件,兄弟组件等,但是这样就会涉及到不同组件需要互相使用其中的某个值的问题 ...

  2. 微信小程序——1、自定义顶部渐变色2、封装好的自定义顶部栏(父组件获取子组件的点击事件)

    1.自定义顶部渐变色 第一种使用代码实现渐变 效果图: .json代码 "navigationStyle":"custom" .wxml代码 <view ...

  3. angular使用@viewChild父组件获取子组件的数据和方法

    一. 父组件通过局部变量获取子组件的引 用  ,主动获取子组件的数据和方法 1. 使用#给子组件命名为#footer <app-footer #footer></app-footer ...

  4. vue/uniapp父组件获取子组件内的数据或方法

    1.父组件主动获取子组件中的数据和方法 在父组件里面通过: ``` this.$refs.childMethod.属性 this.$refs.childMethod.方法 ``` 在父组件中:(调用子 ...

  5. Vue进阶(幺贰零):父组件获取子组件验证结果

    文章目录 一.前言 二.代码实现 三.拓展阅读 一.前言 在开发Vue项目过程中,代码复用之自定义组件是常做事情.当子组件为form表单的时候,父组件需要获取子组件(表单)的验证结果. 尽管有 pro ...

  6. 子组件向父组件传值,父组件获取子组件值

    子组件如何传值给父组件? 父组件将一个方法赋值给一个属性props传递给子组件,子组件在函数被应用时调用父组件传来的属性并传值,父组件可在自身的函数中接受子组件传递过来的值. 父组件 //father ...

  7. rn 函数式组件获取子组件的实例

    class式组件要获取子组件的实例只要用ref就可以了,但是函数式组件就要复杂一点 函数式组件要给子组件直接绑定ref是不成功的,要求子组件使用forward创建才可以,如下 const ChildR ...

  8. antd如何获取表单的值_antd 父组件获取子组件中form表单的值

    还是拿代码来讲吧,详情见注释 子组件 import React, { Component } from 'react'; import { Form, Input } from 'antd'; con ...

  9. react学习(37)----获取子组件得实例

    onRef={(ref) => {this.uploadImg = ref;}}

  10. vue ref是在组件里唯一吗_父组件伸手子组件的方式总结

    1. 前言 这篇文章就是总结react,vue父组件如何伸手获取子组件的数据以及调用子组件方法的. 2. react 以下的代码都是基于16.8版本. 2.1 类组件 react在hook出来前,只要 ...

最新文章

  1. k8s 去除master节点污点NoSchedule,添加master节点 尽量不调度
  2. cannot be cast to org.springframework.web.accept.ContentNegotiationManager
  3. Java8-Lambda表达式
  4. HDU 1412 {A} + {B}
  5. 笔记28 接受请求的输入 ——处理表单
  6. iOS 里面如何使用第三方应用程序打开自己的文件,调用wps其他应用打开当前应用里面的的ppt doc xls...
  7. WPF 2D绘图(2)Geometry
  8. 基于JAX-WS的webService开发实例
  9. qt调用mysql调用了存储过_Qt调用Server SQL中的存储过程
  10. C#LeetCode刷题之#888-公平的糖果交换(Fair Candy Swap)
  11. extjs 获取id的值_Extjs combox获取显示值和ID值
  12. 自定义ContentProvider
  13. sql in关键字使用长度超过1000问题处理
  14. java实验——回文是一种“从前向后读”和“从后向前读”都相同的字符串,如“上海自来水来自海上”。设计一个程序,判断字符串是否是回文。
  15. Silverlight/Windows8/WPF/WP7/HTML5周学习导读(10月29日-11月4日)
  16. indiegogo众筹
  17. 帮我写一段描写时间过得很快,但是自己又很不想时间过得那么快的小作文
  18. 薇诺娜如何以创新战略在新消费浪潮中屹立不倒
  19. 【软考中级】软件设计师学习笔记
  20. Matlab图形绘制(一)三维曲线

热门文章

  1. k8s高可用二进制部署
  2. 矢量导数——角速度与矢量的叉乘
  3. 2017最新版《土地利用现状分类》GBT 21010-2017‰
  4. 力扣刷题-动态规划算法3:完全背包问题
  5. 电脑如何开启卓越性能模式
  6. 教育培训机构如何利用小程序招生?
  7. 微信小程序—智能停车
  8. STM32学习笔记——HC05
  9. C++ 取模、求余运算
  10. 短信平台API接口demo示例-JAVA/Message/XSend