React中ref的四种使用方法

个人公众号

公众号文章-React中ref的四种使用方法
个人公众号,求关注公众号~ 求指导,求点赞,求评论。

写在前面的废话

什么时候使用ref的环境就不说了,比如我们要获取一个输入框的value,无法通过state去获取,这时候用ref就很合适。

本文的重点介绍的是ref的四种方法,因为现在使用的react版本是18.2,所以部分的方法都算是已经过时了,并有自己的局限性,所以如果方便,更推荐使用useRef的方式。

stringRef

在描述stringRef之前,先贴上一段官网中关于stringRef的描述。

如果你以前使用过 React,你可能熟悉一个较旧的 API,其中属性是一个字符串,比如 ,而 DOM 节点被访问为 .我们建议不要这样做,因为字符串引用存在一些问题,被认为是遗留的,并且可能会在将来的某个版本中删除。
在知道了字符串的ref问题之后,由于部分旧的代码我们还会使用到stringRef,我们还是得看看stringRef的使用。

import { PureComponent, ReactNode } from "react";class RefComponent extends PureComponent {
  handleClick = () => {
    const element: any = this.refs.stringRef;
    console.log(element?.value);
  };
  render(): ReactNode {
    return (
      <div>
        <input ref="stringRef" />
        <button
          onClick={() => {
            this.handleClick();
          }}
        >
          点击获取输入框的值
        </button>
      </div>
    );
  }
}export default RefComponent;

效果如下:
在这里插入图片描述

当点击了我们的按钮的时候,就直接获取到了输入框中的值。

而在控制台中也有这么一个警告

Warning: A string ref, “stringRef”, has been found within a strict
mode tree. String refs are a source of potential bugs and should be
avoided. We recommend using useRef() or createRef() instead.

Learn more about using refs safely here:
https://reactjs.org/link/strict-mode-string-ref

而这个警告也与官网的提示一样,讲述了stringRef是一个"deprecated"的API,建议我们使用useRef或者是createRef这两个API。
除此之外,在第五行的代码中,由于我们使用了this,而只有在类组件中,才存在了this,因此我们无法在函数组件中使用到stringRef。
综上所述,不建议再使用stringRef,除非你的项目很老,只能使用stringRef。

createRef

相对于stringRef,createRef算是比较正常点的,而因为stringRef有bug的原因,所以react也推荐在class组件使用createRef。

与直接使用stringRef不同,我们需要先在constructor中,使用createRef构建一个ref对象,再将其绑定到元素上去,这样子才可以去获取到元素。代码如下:

import React, { PureComponent, ReactNode, RefObject } from "react";class RefComponent extends PureComponent {
  inputRef: RefObject<HTMLInputElement> | undefined;
  constructor(props: {} | Readonly<{}>) {
    super(props);
    this.inputRef = React.createRef();
  }
  handleClick = () => {
    const element: any = this.inputRef;
    console.log(element?.current?.value);
  };
  render(): ReactNode {
    return (
      <div>
        <input ref={this.inputRef} />
        <button
          onClick={() => {
            this.handleClick();
          }}
        >
          点击获取输入框的值
        </button>
      </div>
    );
  }
}export default RefComponent;


需要注意的是,我们无法再直接使用ref.value的方式去获取到值,而是需要使用ref?.current?.value的方式获取到值。

而将createRef放置在constructor中的原因,是因为如果放在

componentDidMount的时候,很容易出现createRef未能完成初始化,会出现undefined,同时,也最好使用?.的形式,防止放在constructor的时候,也未能及时初始化的情况。
同样的,本代码也只能放在类组件中使用,无法放在函数组件中使用,因为没有this…
也需要注意一点,这儿我用的类型是RefObject,而部分同学喜欢用LegacyRef,后者泛指的是Ref类型,是兼容之前stringRef的版本。
效果如下:
在这里插入图片描述

CallbackRef

ref属性,除了可以接受ref对象之外,也可以接受函数,这就称之为CallbackRef,也没啥好讲的,代码如下

import React, { LegacyRef, PureComponent, ReactNode, RefObject } from "react";class RefComponent extends PureComponent {
  inputRef: HTMLElement | undefined | null;handleClick = () => {
    const element: any = this.inputRef;
    console.log(element?.value);
  };
  render(): ReactNode {
    return (
      <div>
        <input
          ref={(ref) => {
            this.inputRef = ref;
          }}
        />
        <button
          onClick={() => {
            this.handleClick();
          }}
        >
          点击获取输入框的值
        </button>
      </div>
    );
  }
}export default RefComponent;

需要注意的是,这次的inputRef并不是RefObject,而是一个html对象,所以我们只需要当他做一个html对象处理就好了。

唯一要注意的是,依旧需要在类组件中使用,无法在函数组件中使用,毕竟都是对ref的操作。

useRef

与前面的类组件中对ref对象的操作,函数组件在获得了hook之后,也出现了对应的useRef钩子与之对应。毕竟ref对象都是只能在类组件中使用,前三个方式,无论怎么说,本质都是在类组件中对ref属性做一些变种,而useRef在函数式编程为王道的今天,更加的需要了解。
useRef返回的是一个可变的ref对象,类型为refObject,所以依旧需要用到上面的current属性去读取我们要的值。
useRef需要我们先使用userRef,接着在ref属性上使用回调函数的方式绑定ref。代码如下:

import { useRef } from "react";function RefComponent() {
  const inputRef = useRef<HTMLElement | null>();
  const handleClick = () => {
    const element: any = inputRef;
    console.log(element?.current?.value);
  };
  return (
    <>
      <input
        ref={(ref) => {
          inputRef.current = ref;
        }}
      />
      <button
        onClick={() => {
          handleClick();
        }}
      >
        点击获取输入框的值
      </button>
    </>
  );
}
export default RefComponent;


效果如下:

在这里插入图片描述

最后的废话

大人,现在已经是2023年的年尾了,别想那么多了,用useRef吧…不要搞那么多事情了。

  • 24
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值