React中Hooks几个有用的 ref

先看下来自官方的介绍,当你希望组件"记住"某些信息,但又不想让这些信息 触发新的渲染 时,你可以使用 ref

  • 如何向组件添加 ref
  • 如何更新 ref 的值
  • ref 与 state 有何不同
  • 如何安全地使用 ref

1.给你的组件添加 ref

你可以通过从 React 导入 useRef Hook 来为你的组件添加一个 ref:

import { useRef } from 'react';

export default function Counter() {
  let ref = useRef(0);

  function handleClick() {
    ref.current = ref.current + 1;
    alert('你点击了 ' + ref.current + ' 次!');
  }

  return (
    <button onClick={handleClick}>
      点击我!
      {ref.current}
    </button>
  );
}

在你的组件内,调用 useRef Hook 并传入你想要引用的初始值作为唯一参数。这里的 ref 引用的值是"0",点击后也不变。

以下是 state 和 ref 的对比:

ref state
useRef(initialValue)返回 { current: initialValue } useState(initialValue) 返回 state 变量的当前值和一个 state 设置函数 ( [value, setValue])
更改时不会触发重新渲染 更改时触发重新渲染。
可变 ------ 你可以在渲染过程之外修改和更新 current 的值。 "不可变" ------ 你必须使用 state 设置函数来修改 state 变量,从而排队重新渲染。
你不应在渲染期间读取(或写入) current 值。 你可以随时读取 state。但是,每次渲染都有自己不变的 state 快照

2.使用 ref 操作 DOM

由于 React 会自动处理更新 DOM 以匹配你的渲染输出,因此你在组件中通常不需要操作 DOM。但是,有时你可能需要访问由 React 管理的 DOM 元素 ------ 例如,让一个节点获得焦点、滚动到它或测量它的尺寸和位置。在 React 中没有内置的方法来做这些事情,所以你需要一个指向 DOM 节点的 ref 来实现。

示例: 使文本输入框获得焦点

在本例中,单击按钮将使输入框获得焦点:

import { useRef } from 'react';

export default function Form() {
  const inputRef = useRef(null);

  function handleClick() {
    inputRef.current.focus();
  }

  return (
    <>
      <input ref={inputRef} />
      <button onClick={handleClick}>
        聚焦输入框
      </button>
    </>
  );
}

如何使用 ref 回调管理 ref 列表

  • 这里使用map搭配useRef作存储

    import { useRef } from 'react';

    export default function CatFriends() {
    const itemsRef = useRef(null);

    function scrollToId(itemId) {
      const map = getMap();
      const node = map.get(itemId);
      node.scrollIntoView({
        behavior: 'smooth',
        block: 'nearest',
        inline: 'center'
      });
    }
    
    function getMap() {
      if (!itemsRef.current) {
        // 首次运行时初始化 Map。
        itemsRef.current = new Map();
      }
      return itemsRef.current;
    }
    
    return (
      <>
        <nav>
          <button onClick={() => scrollToId(0)}>
            Tom
          </button>
          <button onClick={() => scrollToId(5)}>
            Maru
          </button>
          <button onClick={() => scrollToId(9)}>
            Jellylorum
          </button>
        </nav>
        <div>
          <ul>
            {catList.map(cat => (
              <li
                key={cat.id}
                ref={(node) => {
                  const map = getMap();
                  if (node) {
                    map.set(cat.id, node);
                  } else {
                    map.delete(cat.id);
                  }
                }}
              >
                <img
                  src={cat.imageUrl}
                  alt={'Cat #' + cat.id}
                />
              </li>
            ))}
          </ul>
        </div>
      </>
    );
    

    }

    const catList = [];
    for (let i = 0; i < 10; i++) {
    catList.push({
    id: i,
    imageUrl: 'https://placekitten.com/250/200?image=' + i
    });
    }

itemsRef 保存的不是单个 DOM 节点,而是保存了包含列表项 ID 和 DOM 节点的 Map。(Ref 可以保存任何值!) 每个列表项上的 ref 回调负责更新 Map。

3.访问另一个组件的 DOM 节点

当你将 ref 放在像 <input /> 这样输出浏览器元素的内置组件上时,React 会将该 ref 的 current 属性设置为相应的 DOM 节点(例如浏览器中实际的 <input /> )。

但是,如果你尝试将 ref 放在 你自己的 组件上,例如 <MyInput />,默认情况下你会得到 null。这个示例演示了这种情况。请注意单击按钮 并不会 聚焦输入框:

相关推荐
余生H5 分钟前
前端Python应用指南(三)Django vs Flask:哪种框架适合构建你的下一个Web应用?
前端·python·django
LUwantAC14 分钟前
CSS(四)display和float
前端·css
cwtlw18 分钟前
CSS学习记录20
前端·css·笔记·学习
界面开发小八哥22 分钟前
「Java EE开发指南」如何用MyEclipse构建一个Web项目?(一)
java·前端·ide·java-ee·myeclipse
谢道韫66630 分钟前
今日总结 2024-12-24
javascript·vue.js·elementui
一朵好运莲31 分钟前
React引入Echart水球图
开发语言·javascript·ecmascript
米奇妙妙wuu37 分钟前
react使用sse流实现chat大模型问答,补充css样式
前端·css·react.js
傻小胖42 分钟前
React 生命周期完整指南
前端·react.js
梦境之冢1 小时前
axios 常见的content-type、responseType有哪些?
前端·javascript·http
racerun1 小时前
vue VueResource & axios
前端·javascript·vue.js