Skip to content

❤React-ref和useRef

1、认识ref

(1)简介

  • ref 是 英文 reference 的简写,其含义为“引用”。
  • 在 React 中,ref 主要用于获取组件实例或访问 DOM 节点,也可以用于组件间通信。它是一个普通的 JavaScript 对象,拥有一个名为 current 的属性。
  • 它的创建方式有两种,createRef 和 useRef。

需要注意:ref对象都是只能在类组件中使用

(2) 历史(stringRef演变)

在认清ref之前,我们先来简单认识一下stringRef。

官网中关于stringRef的描述是:

如果你以前使用过 React,你可能熟悉一个较旧的 API,其中属性是一个字符串 ,而 DOM 节点被访问为.我们建议不要这样做,因为字符串引用存在一些问题,被认为是遗留的,并且可能会在将来的某个版本中删除。

stringRef在类组件之中使用如下:

js
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;

写法上我们可以看出,其实跟我们的ref写法基本上差不多

官网提示我们stringRef是一个"deprecated"的API,建议我们使用useRef或者是createRef这两个API。 只有在类组件中,才存在了this,因此我们无法在函数组件中使用到stringRef。 除非项目很老,不然别用stringRef。

(3) 使用

什么时候使用ref: 举个例子:我们要获取一个输入框的value,无法通过state去获取,这时候用ref。

随着Reactd对于函数式的推荐,ref的讲解我们也主要以函数式为主!

2、ref简单使用和认识

在我们的src目录下面新建一个文件03-ref.js

plain
src
  => demo
  => ref.js

App.js文件之中进行导入

js
import Demo from './demo/03-ref.js'

先通过input来看看在函数组件之中ref最简单的使用,然后我们可以看看输出的是什么

先给他绑定一下ref和事件

js
 <input
    id="insertArea"
    className="input"
    value={this.state.inputValue}
    onChange={this.handleInputChange}
    ref={(input) => { this.input = input }}
/>


handleInputChange() {
        console.log(this.input, 'this.input');
        const value = this.input.value

        this.setState(() => ({
            inputValue: value
        }))
    }

然后我们可以看到输出的结果如下:

如何拿到值呢?

通过this.input.value拿到值

3、createRef(直接可略过-类组件之中推荐使用)

createRef算是类组件之中承接stringRef吧,不过现在函数编程王道的世界,大致写法如下,可直接跳过!

js
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;

4、函数组件useRef的使用(建议推荐性写法)

接下来通过input来看看在函数组件之中ref最简单的使用useRef

js
import { useState, useRef } from 'react';

export default function Chat() {
  const [text, setText] = useState('');
  const textRef = useRef(text);

  function handleChange(e) {
    setText(e.target.value);
    textRef.current = e.target.value;
  }

  function handleSend() {
    console.log(textRef.current,'textRef.current');
  }

  return (
    <>
      <input
        value={text}
        onChange={handleChange}
      />
      <button
        onClick={handleSend}>
        发送
      </button>
      <div>{text}</div>
    </>
  );
}

直接输出一下可以看到我们已经拿到了input上面的参数和值

总结一下就是三部分:引入\绑定值\拿值

js
1 引入 
import { useState, useRef } from 'react';

2 绑定值
const [text, setText] = useState('');
const textRef = useRef(text);
value={text}

3 拿值

function handleChange(e) {
    setText(e.target.value);
    textRef.current = e.target.value;
}

这样子下来我们就拿到了我们的useRef使用的值

4、useRef

useRef返回的是一个可变的ref对象,类型为refObject,需要用到current属性去读取我们要的值。

useRef需要我们先使用userRef,接着在ref属性上使用回调函数的方式绑定ref

useref.js 里面我们手写如下

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

最后我们可以看到输出的'element.current'和'element.current.value'的值如下图所示:

2024年了,那就直接用useRef啊肯定!

Released under the MIT License.