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。这个示例演示了这种情况。请注意单击按钮 并不会 聚焦输入框:

相关推荐
清灵xmf19 分钟前
TypeScript 类型进阶指南
javascript·typescript·泛型·t·infer
小白学大数据25 分钟前
JavaScript重定向对网络爬虫的影响及处理
开发语言·javascript·数据库·爬虫
qq_3901617734 分钟前
防抖函数--应用场景及示例
前端·javascript
334554321 小时前
element动态表头合并表格
开发语言·javascript·ecmascript
John.liu_Test1 小时前
js下载excel示例demo
前端·javascript·excel
Yaml41 小时前
智能化健身房管理:Spring Boot与Vue的创新解决方案
前端·spring boot·后端·mysql·vue·健身房管理
PleaSure乐事1 小时前
【React.js】AntDesignPro左侧菜单栏栏目名称不显示的解决方案
前端·javascript·react.js·前端框架·webstorm·antdesignpro
哟哟耶耶1 小时前
js-将JavaScript对象或值转换为JSON字符串 JSON.stringify(this.SelectDataListCourse)
前端·javascript·json
getaxiosluo1 小时前
react jsx基本语法,脚手架,父子传参,refs等详解
前端·vue.js·react.js·前端框架·hook·jsx
理想不理想v1 小时前
vue种ref跟reactive的区别?
前端·javascript·vue.js·webpack·前端框架·node.js·ecmascript