ForwardRef useImperativeHandle方法demo

 更新时间:2023年03月19日 09:26:31   作者:好好吃饭好好睡觉  
这篇文章主要为大家介绍了ForwardRef useImperativeHandle方法demo,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

一、获取Ref的方式

  • 使用字符串
  • 使用函数
  • 使用Ref对象(最常见)
  • 使用createRef
export class RefTest extends React.Component {
    currentDom: React.RefObject<HTMLDivElement> = React.createRef();
    currentChildren: React.LegacyRef<Children> = React.createRef();
    render() {
        console.log(this.currentChildren, this.currentDom);
    return (
        <>
            <div ref = { this.currentDom }>你好</div>
            <Children ref = { this.currentChildren}></Children>
        </>
       )
    }
}

  • 使用useRef
export const RefTest = () => {
    const currentDom = useRef(null);
    const currentChildren = useRef(null);
    useEffect(() => {
        console.log(currentChildren, currentDom, '这里也可以打印出来了');
     },[])
   return (
   <>
       <div ref = { currentDom }>你好</div>
       <Children ref = { currentChildren }></Children>
   </>
    )
}

二、Ref实现组件通信

  • 既然ref可以获取到子组件的实例,那么就可以拿到子组件上的状态和方法,从而可以实现组件之间的通信

来个极简版

import React, { useEffect } from 'react';
class Son extends React.Component{
    state={
        sonValue:''
    }
    render(){
    return <div>
        <div>子组件的信息: {this.state.sonValue}</div>
        <div>对父组件说</div>
        <input onChange{(e)=>this.props.setFather(e.target.value)}/>
        </div>
    }
}
export default function Father(){
const [ fatherValue , setFatherValue ] = React.useState('')
const sonRef = React.useRef(null)
return <div>
    <div>父组件的信息: {fatherValue}</div>
    <div>对子组件说</div>
    <input onChange = { (e) => sonRef.current.setState( {sonValue: e.target.value})}/>
    <Son ref={sonRef} setFather={setFatherValue}/>
    </div>
}

三、ForwardRef

  • 上面说的三种都是组件去获取其DOM元素或者子组件的实例,当开发变得复杂时,我们可能有将ref跨层级捕获的需求,也就是可以将ref进行转发

比如跨层级获取ref信息

  • 来个例子, 我们希望能够在GrandFather组件获取到Son组件中
![图片转存失败,建议将图片保存下来直接上传
        import React from 'react';
interface IProps {
    targetRef: React.RefObject<HTMLDivElement>
    otherProps: string
}
interface IGrandParentProps {
    otherProps: string
}
class Son extends React.Component<IProps> {
    constructor(props) {
        super(props);
        console.log(props,'son中的props');
     }
     render() {
         // 最终目标是获取该DOM元素的信息
         return <div ref= { this.props.targetRef }>真正目的是这个</div>
     }
}
class Farther extends React.Component<IProps> {
    constructor(props) {
        super(props)
        console.log(props, 'father中的props');
    }
    render() {
        return (
        // 继续将ref传给Son
            <Son targetRef={this.props.targetRef} {...this.props} />
         )
    }
}
// 在这里使用了forwardRef, 相当于把传入的ref转发给Father组件
const ForwardRef = React.forwardRef((props: IGrandParentProps, ref: React.RefObject<HTMLDivElement>) 
    => <Farther targetRef={ref} {...props}/>)

 image.png(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5d49e7ff4ec940b28dcb3a780fd5c0a7~tplv-k3u1fbpfcp-watermark.image?)
export class GrandFather extends React.Component {
    currentRef:React.RefObject<HTMLDivElement> = React.createRef();
    componentDidMount() {
        // 获取到的Ref信息
        console.log(this.currentRef, 'componentDidMount');
    }
    render() {
        return (
        <ForwardRef ref={this.currentRef} otherProps = '正常传递其他props' />
        )
    }
}
]()
  • 打印结果: 其实就是利用了forwardRef,把 ref 变成了可以通过 props 传递和转发

四、 useImperativeHandle

  • 上面我们一直说的都是获取子组件的实例,但是实际上我们函数组件是没有实例的,故我们需要借助useImperativeHandle, 使用forwardRef+useImperativeHandle就可以在函数组件中流畅地使用ref
  • useImperativeHandle可以传入三个参数:
    • ref: 可以接受forwardRef传入的ref
    • handleFunc: 返回值作为暴露给父组件的ref对象
    • deps: 依赖项,当依赖项改变的时候更新形成的ref对象

看完参数其实就能够清楚地知道它的作用了,可以通过forwardRef+useImperativeHandle自定义获取到的ref信息

再来两个简单例子:

import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from "react"
const ForwardItem = forwardRef((props, ref) => {
    const [sonValue, setSonValue] = useState('修改之前的值');
    useImperativeHandle(ref, () => ({
        setSonValue,
    }))
    return (
        <div>子组件的值: {sonValue}</div>
    )
})
export const Father = () => {
    const testRef = useRef(null);
    useEffect(() => {
        console.log(testRef.current, 'ref获取到的信息')
     })
    const changeValue = () => {
        const DURATION = 2000;
        setTimeout(() => {
        testRef.current.setSonValue('我已经修改值啦')
        },DURATION)
    }
    return (
    <>
       <ForwardItem ref={ testRef }/>
       <button onClick={() => changeValue()}>2s后修改子组件ForwardItem的值</button>
    </>
    )
}

  • 父组件希望直接调用函数子组件的方法
    • 这里让useImperativeHandle形成了有setSonValue的ref对象,然后再在父组件调用该方法
  • 父组件希望获取到子组件的某个DOM元素
const ForwardItem = forwardRef((props, ref) => {
    const elementRef: RefObject<HTMLDivElement> = useRef();
    useImperativeHandle(ref, () => ({
        elementRef,
    }))
    return (
        <div ref = { elementRef }>我是一个子组件</div>
     )
})
export const Father = () => {
    const testRef = useRef(null);
    useEffect(() => {
        console.log(testRef.current, 'ref获取到的信息')
     })
    return (
    <>
        <ForwardItem ref={ testRef }/>
    </>
    )
}

当然useRef还可以在函数组件中缓存数据,这个就不多叨叨啦,更多关于ForwardRef useImperativeHandle的资料请关注脚本之家其它相关文章!

相关文章

  • 解读useState第二个参数的"第二个参数"

    解读useState第二个参数的"第二个参数"

    这篇文章主要介绍了useState第二个参数的"第二个参数",具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • 30分钟带你全面了解React Hooks

    30分钟带你全面了解React Hooks

    Hooks是一种函数,该函数允许您从函数式组件 “勾住(hook into)”React状态和生命周期功能。Hooks在类内部不起作用 - 它们允许你无需类就使用 React。
    2021-05-05
  • react  Suspense工作原理解析

    react  Suspense工作原理解析

    这篇文章主要为大家介绍了react  Suspense工作原理解析以及基本应用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • webpack手动配置React开发环境的步骤

    webpack手动配置React开发环境的步骤

    本篇文章主要介绍了webpack手动配置React开发环境的步骤,webpack手动配置一个独立的React开发环境, 开发环境完成后, 支持自动构建, 自动刷新, sass语法 等功能...感兴趣的小伙伴们可以参考一下
    2018-07-07
  • React Native使用百度Echarts显示图表的示例代码

    React Native使用百度Echarts显示图表的示例代码

    本篇文章主要介绍了React Native使用百度Echarts显示图表的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-11-11
  • react使用axios实现上传下载功能

    react使用axios实现上传下载功能

    这篇文章主要为大家详细介绍了react使用axios实现上传下载功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • 一文详解手动实现Recoil状态管理基本原理

    一文详解手动实现Recoil状态管理基本原理

    这篇文章主要为大家介绍了一文详解手动实现Recoil状态管理基本原理实例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05
  • React Native实现简单的登录功能(推荐)

    React Native实现简单的登录功能(推荐)

    这篇文章主要介绍了React Native实现登录功能的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-09-09
  • React使用高阶组件与Hooks实现权限拦截教程详细分析

    React使用高阶组件与Hooks实现权限拦截教程详细分析

    高阶组件就是接受一个组件作为参数并返回一个新组件(功能增强的组件)的函数。这里需要注意高阶组件是一个函数,并不是组件,这一点一定要注意,本文给大家分享React高阶组件使用小结,一起看看吧
    2023-01-01
  • react+antd+upload结合使用示例

    react+antd+upload结合使用示例

    这篇文章主要为大家介绍了react+antd+upload结合使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05

最新评论