React中ref的四种使用方法

个人公众号

公众号文章-React中ref的四种使用方法

个人公众号,求关注公众号~ 求指导,求点赞,求评论。

写在前面的废话

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

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

stringRef

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

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

javascript 复制代码
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: reactjs.org/link/strict...

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

createRef

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

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

javascript 复制代码
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,也没啥好讲的,代码如下

javascript 复制代码
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。代码如下:

javascript 复制代码
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吧...不要搞那么多事情了。

相关推荐
前端鳄鱼崽38 分钟前
【react-native-inspector】全网唯一开源 react-native 点击组件跳转到编辑器
前端·react native·react.js
用户984022766791838 分钟前
【React.js】渐变环形进度条
前端·react.js·svg
demi_meng9 小时前
reactNative 遇到的问题记录
javascript·react native·react.js
千码君201610 小时前
React Native:从react的解构看编程众多语言中的解构
java·javascript·python·react native·react.js·解包·解构
JamSlade14 小时前
流式响应 sse 系统全流程 react + fastapi为例子
前端·react.js·fastapi
徐同保14 小时前
react useState ts定义类型
前端·react.js·前端框架
liangshanbo121514 小时前
React 19 vs React 18全面对比
前端·javascript·react.js
腹黑天蝎座17 小时前
浅谈React19的破坏性更新
前端·react.js
醉方休18 小时前
React 官方推荐使用 Vite
前端·react.js·前端框架