React useRef Hook:不仅适用于 DOM 元素
修复:现在可以在已有 StarSearch 聊天记录的情况下发起新的聊天 #3637
在这篇文章中,我们将介绍什么useRef是钩子,它的一些使用示例,以及何时不应该使用它。
useRef是什么?
该钩子会创建一个引用对象,该对象在其currentuseRef属性中存储一个可变值。该值可以是任何内容,从 DOM 元素到普通对象。与通过useState等钩子维护组件状态不同,通过该钩子修改引用对象不会触发组件的重新渲染,从而提升性能。useRef
示例
使用 useRef Hook 引用 DOM 元素
在 React 中,状态(state)管理着可能触发页面重新渲染的数据。但是,如果您需要一种直接访问文档对象模型(DOM)元素的方法,而这些元素又不应该导致页面重新渲染,该怎么办呢?这时就需要用到useRef hook 了。
通常情况下,你会这样做。
import { useEffect, useRef } from "react";
export const SomeComponent = () => {
const firstNameInputRef = useRef<HTMLInputElement>(null);
// for plain JavaScript change the above line to
// const firstNameInputRef = useRef(null);
useEffect(() => {
firstNameInputRef.current?.focus();
}, []);
return (
<form>
<label>
First Name:
<input type="text" ref={firstNameInputRef}/>
</label>
</form>
);
}
- 我们创建一个名为
firstNameInputRefusing的变量useRef来引用 DOM 元素(初始值为 null),并使用该变量useEffect在初始渲染时聚焦输入元素。 - 在内部
useEffect,我们检查输入框是否firstNameInputRef.current存在(初始渲染后它就是实际的 DOM 元素)。如果存在,我们就调用方法focus()将焦点设置到输入框上。
使用 useRef Hook 引用非 DOM 元素
最近,我一直在参与 Open Sauced 的StarSearch 项目,这是一个类似 Copilot for git history 的功能,我们已于 2024 年 5 月底发布。您可以在下面的博客文章中阅读更多关于 StarSearch 的信息。
请求内容是能够发起一个新的 StarSearch 对话。为此,我必须先停止当前的对话。如果您使用过OpenAI API 或类似的 API,它们通常会返回一个ReadableStream作为响应。
ReadableStream 是一种 Web API,它允许在数据可用时分块读取数据,从而能够高效地处理大型或实时数据集。在 API 响应的上下文中,这意味着我们可以立即开始处理数据,而无需等待整个响应完成。
我最初实现了这个功能,但如果响应开始以流的形式传输,就会出现问题。解决方案是通过钩子创建一个对可读流的引用useRef,并在开始新的对话时取消正在进行的对话。您可以在下面的拉取请求 (PR) 中看到这些更改。
修复:现在可以在已有 StarSearch 聊天记录的情况下发起新的聊天 #3637
现在,新对话开始时的isRunning状态会重置false。这之前会导致在取消上一个对话并开始新对话时,无法启动新的对话流。
修复 #3636
前
后
- 前往任意工作区并打开 StarSearch
- 开始对话
- 点击 StarSearch 简洁标题栏中的“返回”按钮或“新建对话”按钮即可取消对话。
- 开始新的对话。
- 注意新加入的对话。
- [ ] 一级
- [ ] 二级
- [ ] 三级
- [x] 第四层
所以现在,如果有人按下“创建新对话”按钮,我会取消 StarSearch 当前正在播放的响应,例如
const streamRef = useRef<ReadableStreamDefaultReader<string>>();
// for plain JavaScript change the above line to
// const streamRef = useRef();
...
const onNewChat = () => {
streamRef.current?.cancel();
...
};
...
- 我们创建一个名为
streamRefusing的变量来保存对当前ReadableStreamDefaultReader 的useRef引用。 - 该
onNewChat函数检查是否streamRef.current存在(意味着流正在进行中)。 - 如果存在一个信息流,我们会在开始新的对话之前调用
cancel()停止streamRef.current该信息流。
总结
useRef这完美地解决了我的使用场景。或许你会发现这个useRef钩子除了用于引用 DOM 元素之外,在其他方面也很有用。
你可以通过钩子将几乎任何内容存储在引用对象中useRef,这不会导致组件重新渲染。如果你要持久化组件状态,请选择useState其他钩子,例如 `setState` 或 `return`,useReducer这样组件才会重新渲染。
如需进一步了解useRefuseRef hook,我强烈建议查阅 React 文档。
保持你的个性!
如果您想了解更多关于我在开源领域的工作,请在 OpenSauced 上关注我。
文章来源:https://dev.to/opensauced/the-react-useref-hook-not-just-for-html-elements-3cf3