发布于 2026-01-06 2 阅读
0

理解 React 中 useRef hook 和 forwardRef 的用法

理解 React 中 useRef hook 和 forwardRef 的用法

React 中的useRef hook 用于创建对 HTML 元素的引用。最常见的应用场景是当我们有表单元素,需要引用这些表单元素来打印它们的值或获取它们的焦点等

因此,{useRef} hook 与其他 react hook 一样,是从“react”导入的,我们在函数组件中使用它们来创建引用,并且可以通过使用“ref”属性将其分配给jsx中的 html 元素

下面展示了如何使用useRef钩子函数——



import React, { useEffect, useRef } from "react";

const UseRefHookExplained = (props) => {
  // Creating refs for username and password
  const userNameRef = useRef(null);
  const passwordRef = useRef(null);

  // We are also creating a reference to the Login button
  const submitBtnRef = useRef(null);

  // useEffect to set the initial focus to the user name input
  useEffect(() => {
    userNameRef.current.focus();
  }, []);

  // This function is used to handle the key press.
  // Whenever user hits enter it moves to the next element
  const handleKeyPress = (e, inputType) => {
    if (e.key === "Enter") {
      switch (inputType) {
        // Checks if Enter pressed from the username field?
        case "username":
          // Moves the focus to the password input field
          passwordRef.current.focus();
          break;
        // Checks if Enter pressed from the password field?
        case "password":
          // Moves the focus to the submit button
          submitBtnRef.current.focus();
          e.preventDefault();
          break;
        default:
          break;
      }
    }
  };

  // Function to handle the submit click from the button
  const handleSubmit = () => {
    alert("submitted");
  };

  // getting the style as prop from the parent.
  // Basic style to center the element and apply a bg color
  const { style } = props;
  return (
    <div style={style}>
      <h2>Example for using useRef Hook</h2>
      <h3>Login</h3>
      <input
        type="text"
        name="username"
        ref={userNameRef}
        onKeyDown={(e) => handleKeyPress(e, "username")}
      />
      <input
        type="password"
        name="password"
        ref={passwordRef}
        onKeyDown={(e) => handleKeyPress(e, "password")}
      />
      <button ref={submitBtnRef} onClick={handleSubmit}>
        Login
      </button>
    </div>
  );
};

export default UseRefHookExplained;




Enter fullscreen mode Exit fullscreen mode

因此, useRef hook的概念非常简单,正如您在上面的代码中看到的那样。请按照以下步骤操作 -

  1. 我们从 React 导入 useRef hook。
  2. 我们初始化这个钩子(例如:const inputRef = useRef(null)
  3. 创建的引用通过“ref”属性附加到html元素上。

现在我们可以随时引用这个元素,以便进行诸如获取值、聚焦等操作。


页面加载时的输出初始状态 -
image.png

输入用户名并按下回车键后的焦点状态 -
image.png

输入密码并点击“确认”后,焦点状态转移到按钮上。

image.png

所以,现在这一点应该很清楚了。接下来,我们来看一个使用另一个 React 组件作为输入的场景。

在这种情况下,将我们在父组件中定义的引用作为属性传递给子组件(输入组件)就变得有点困难了。

React 提供了一种处理这种情况的方法,即使用React.forwardRef将 refs 转发给子组件。

让我们查看示例代码以了解更改之处——
(我添加了注释“//new”来标识新添加的代码行)



import React, { useEffect, useRef } from "react";
import Input from "./Input"; // new

const UseRefHookExplained = (props) => {
  // Creating refs for username and password
  const userNameRef = useRef(null);
  const passwordRef = useRef(null);

  // We are also creating a reference to the Login button
  const submitBtnRef = useRef(null);

  // useEffect to set the initial focus to the user name input
  useEffect(() => {
    userNameRef.current.focus();
  }, []);

  // This function is used to handle the key press.
  // Whenever user hits enter it moves to the next element
  const handleKeyPress = (e, inputType) => {
    if (e.key === "Enter") {
      switch (inputType) {
        // Checks if Enter pressed from the username field?
        case "username":
          // Moves the focus to the password input field
          passwordRef.current.focus();
          break;
        // Checks if Enter pressed from the password field?
        case "password":
          // Moves the focus to the submit button
          submitBtnRef.current.focus();
          e.preventDefault();
          break;
        default:
          break;
      }
    }
  };

  // Function to handle the submit click from the button
  const handleSubmit = () => {
    alert("submitted");
  };

  // getting the style as prop from the parent.
  // Basic style to center the element and apply a bg color
  const { style } = props;
  return (
    <div style={style}>
      <h2>Example for using useRef Hook</h2>
      <h3>Login</h3>
      {/* New. Using the Component instead of input element */}
      <Input
        type="text"
        name="username"
        ref={userNameRef}
        onKeyDown={(e) => handleKeyPress(e, "username")}
      />
      {/* New. Using the Component instead of input element */}
      <Input
        type="password"
        name="password"
        ref={passwordRef}
        onKeyDown={(e) => handleKeyPress(e, "password")}
      />
      <button ref={submitBtnRef} onClick={handleSubmit}>
        Login
      </button>
    </div>
  );
};

export default UseRefHookExplained;



Enter fullscreen mode Exit fullscreen mode

现在我们来看一下 Input.js 组件。



import React from "react";

/* In the functional component, a second argument 
is passed called ref, which will have access to 
the refs being forwarded from the parent */
const Input = (props, ref) => {
  /* assigning the ref attribute in input and spreading 
the other props which will contain type, name, onkeydown etc */
  return <input {...props} ref={ref} />;
};

// wrapping the Input component with forwardRef
const forwardedRef = React.forwardRef(Input);

// Exporting the wrapped component
export default forwardedRef;



Enter fullscreen mode Exit fullscreen mode

因此,React.forwardRed 为我们提供了一种方法,使我们能够将父组件中定义的 refs 传递或转发到子组件。

希望你今天学到了新知识!

文章来源:https://dev.to/sajithpradeep/understanding-the-use-of-useeffect-hook-forwardref-in-react-57jf