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

相关推荐
秋田君12 分钟前
Vue3+Node.js 实现大文件上传:断点续传、秒传、分片上传完整教程(含源码)
前端
爱隐身的官人12 分钟前
ctfshow - web - nodejs
前端·nodejs·ctf
zhong liu bin12 分钟前
Vue框架技术详解——项目驱动概念理解【前端】【Vue】
前端·javascript·vue.js·vscode·vue
W-GEO12 分钟前
前端安全攻防:XSS, CSRF 等常见威胁的防范与检测指南
前端·安全·xss
2301_8035545215 分钟前
实习项目包装--HTTP 协议和 Web API
前端·网络协议·http
lssjzmn16 分钟前
Spring Web 异步响应实战:从 CompletableFuture 到 ResponseBodyEmitter 的全链路优化
java·前端·后端·springboot·异步·接口优化
这里有鱼汤17 分钟前
上班族没时间炒股?不妨试试这个隔夜超短战法(附:Python量化源码)
前端
n123523524 分钟前
Chrome 插件开发入门指南:从基础到实践
前端·chrome
前端 贾公子30 分钟前
ElementUI 中 validateField 对部分表单字段数组进行校验时多次回调问题
前端·javascript·elementui
棒棒的唐31 分钟前
vue2 elementUI 登录页面实现回车提交登录的方法
前端·javascript·elementui