以 use
开头的函数被称为 Hook。useState
是 React 提供的一个内置 Hook。你可以在 React API 参考 中找到其他内置的 Hook。你也可以通过组合现有的 Hook 来编写属于你自己的 Hook。
Hook 比普通函数更为严格。你只能在你的组件(或其他 Hook)的 顶层 调用 Hook。如果你想在一个条件或循环中使用 useState
,请提取一个新的组件并在组件内部使用它。
import { useState } from 'react';
我们刚才使用的这个就是一个hook
Hook 可以帮助在组件中使用不同的 React 功能。你可以使用内置的 Hook 或使用自定义 Hook。本页列出了 React 中所有内置 Hook。
状态帮助组件 “记住”用户输入的信息。例如,一个表单组件可以使用状态存储输入值,而一个图像库组件可以使用状态存储所选的图像索引。
使用以下 Hook 以向组件添加状态:
const [index, setIndex] = useState(0);
上下文帮助组件 从祖先组件接收信息,而无需将其作为 props 传递。例如,应用程序的顶层组件可以借助上下文将 UI 主题传递给所有下方的组件,无论这些组件层级有多深。
const theme = useContext(ThemeContext);
ref 允许组件 保存一些不用于渲染的信息,比如 DOM 节点或 timeout ID。与状态不同,更新 ref 不会重新渲染组件。ref 是从 React 范例中的“脱围机制”。当需要与非 React 系统如浏览器内置 API 一同工作时,ref 将会非常有用。
const inputRef = useRef(null);
Effect 允许组件 连接到外部系统并与之同步。这包括处理网络、浏览器、DOM、动画、使用不同 UI 库编写的小部件以及其他非 React 代码。
- function ChatRoom({ roomId }) {
- useEffect(() => {
- const connection = createConnection(roomId);
- connection.connect();
- return () => connection.disconnect();
- }, [roomId]);
Effect 是从 React 范式中的“脱围机制”。避免使用 Effect 协调应用程序的数据流。如果不需要与外部系统交互,那么 可能不需要 Effect。
useEffect
有两个很少使用的变换形式,它们在执行时机有所不同:
优化重新渲染性能的一种常见方法是跳过不必要的工作。例如,可以告诉 React 重用缓存的计算结果,或者如果数据自上次渲染以来没有更改,则跳过重新渲染。
可以使用以下 Hook 跳过计算和不必要的重新渲染:
- function TodoList({ todos, tab, theme }) {
- const visibleTodos = useMemo(() => filterTodos(todos, tab), [todos, tab]);
- // ...
- }
有时由于屏幕确实需要更新,无法跳过重新渲染。在这种情况下,可以通过将必须同步的阻塞更新(比如使用输入法输入内容)与不需要阻塞用户界面的非阻塞更新(比如更新图表)分离以提高性能。
使用以下 Hook 处理渲染优先级:
资源可以被组件访问,而无需将它们作为状态的一部分。例如,组件可以从 Promise 中读取消息,或从上下文中读取样式信息。
使用以下 Hook 以从资源中读取值:
- function MessageComponent({ messagePromise }) {
- const message = use(messagePromise);
- const theme = use(ThemeContext);
- // ...
- }
- 这些 Hook 主要适用于库作者,不常在应用程序代码中使用。
-
- 使用 useDebugValue 自定义 React 开发者工具为自定义 Hook 添加的标签。
- 使用 useId 将唯一的 ID 与组件相关联,其通常与可访问性 API 一起使用。
- 使用 useSyncExternalStore 订阅外部 store。
开发者可以 自定义 Hook 作为 JavaScript 函数。