翻译自:https://reactjs.org/docs/hooks-overview.html
Hooks 是 React 16.8 新增的功能。它允许你在不编写类的情况下使用状态和其他 React 特性。
Hooks 是向后兼容的。本文为经验丰富的 React 用户提供了 Hooks 的概述。这是一个快速讲解的概述。如果你感到困惑,请找这样的概括:
详细解释
阅读动机 以了解我们为何将 Hooks 引入React。
↑↑↑ Each section ends with a yellow box like this. They link to detailed explanations.
↑↑↑ 每一节的结尾都以这样的黄色背景结束(译者的主题不是黄色 2333) 它们链接到到详细的解释。
📌 State Hook
这个示例渲染了一个计数器。当你点击按钮时,它会将值递增1:
import { useState } from 'react'; |
这里的 useState
就是一个 Hook(我们将在稍后解释它的含义)。我们在函数组件中调用它来添加一些内部状态。React 将在多次渲染之间保留此状态。useState
返回一对内容:当前的状态值和更新这个状态值的函数。你可以从事件处理程序或其他位置调用此函数。它类似于类中的this.setState
,除了它不会将旧状态和新状态合并在一起。
(我们将在使用 State Hook 使用示例比较 useState
与 this.state
。)
useState
的唯一参数是初始状态。在上面的例子中,它是 0
,因为我们的计数器从零开始。请注意,与 this.state
不同旳是,状态值不必是对象 – 它可以是任意你希望的类型。初始状态参数仅在第一次渲染时使用。
Declaring multiple state variables
声明多个状态变量
你可以在同一个组件中多次使用 State Hook:
function ExampleWithManyStates() { |
数组解构 语法使我们能够为调用 useState
得到的状态变量赋予不同的名称。这些名字(如上面例子中的 age,fruit, todos 译者注)并不是 useState
API 的一部分。并且 React 指定了,如果多次调用 useState
,则在它们每次渲染时都会以相同的顺序执行。稍后,我们将解释为什么这样以及何时有用。
But what is a Hook?
但是,什么是 Hook 呢?
Hooks 是能让你从函数组件中 “访问” 到 React 状态和生命周期功能的函数。Hooks 在类里不起作用 – 它们能够让你使用 React 不写类的语法。(我们不建议 你立即重写现有的组件,但如果你愿意,可以开始在新组件中使用Hook。)
React provides a few built-in Hooks like useState
. You can also create your own Hooks to reuse stateful behavior between different components. We’ll look at the built-in Hooks first.
React 提供了一些像 useState
这样的内置 Hooks。你还可以创建自己的 Hooks 以方便在不同组件间重用状态行为。我们先来看看内置的 Hooks。
详细说明
你可以在此页面上了解有关 State Hook 的更多信息:使用 State Hook。
⚡️ Effect Hook
你之前很可能在 React 组件执行过数据获取,订阅内容或手动更改 DOM 的操作。我们将这些操作称为“包含副作用的操作”(或简称为“副作用”),因为它们会影响其他组件,并且在渲染中无法完成。
副作用的 Hook,useEffect
增加了从函数组件执行“副作用”的功能。它与 React 类中的componentDidMount
,componentDidUpdate
和 componentWillUnmount
具有相同的用途,但统一为单个API。(我们将在使用副作用 Hook 这个示例中比较它们的差异。)
例如,下面这个组件在 React 更新到 DOM 后设置文档标题:
import { useState, useEffect } from 'react'; |
当调用 useEffect
时,你告诉了 React 在更新 DOM 的后运行你的 effect
函数。effect
在组件内声明,因此可以访问组件的 props 和 state 。默认情况下,React 在每次渲染后都运行 effect
–包括第一次渲染。(我们将在使用 Effect Hook 中更多地讨论它与类生命周期的比较。)
effect
还可以通过返回一个函数来指定如何“清理”它们。例如,下面这个组件使用 effect
来订阅朋友的在线状态,并通过取消订阅函数来清理:
import { useState, useEffect } from 'react'; |
在此示例中,当组件卸载时,或者由于后续渲染而导致重新运行 effect 前,React 都将取消订阅 ChatAPI。
(如果需要的话,有一种方法可以告诉 React 跳过重新订阅,如果我们传递给 ChatAPI 的 props.friend.id 没有改变。)
就像使用 useState
一样,你可以在组件中使用多个 effect:
function FriendStatusWithCounter(props) { |
Hooks 能够让你自由地将组件中相关联的副作用(例如添加和删除订阅)组织在一起,而不是像类组件一样,被不同的生命周期方法强制拆分到不同的方法中。
详细解释
你可以在此页面上了解关于useEffect
的更多信息:使用 Effect Hook。
✌️ Rules of Hooks
Hooks 是 JavaScript 函数,但它强加了两个额外的规则:
- 只在函数顶层调用 Hooks。不要在循环,条件或嵌套函数中调用 Hook。
- Only call Hooks from React function components. Don’t call Hooks from regular JavaScript functions. (There is just one other valid place to call Hooks – your own custom Hooks. We’ll learn about them in a moment.)
- 只在 React 函数组件中调用 Hooks。不要在普通的 JavaScript 函数中调用 Hook。(还有另一个被允许的地方调用 Hooks – 你的自定义 Hooks。我们稍后会介绍它们。)
我们提供了一个linter 插件 来强制执行这些规则。我们知道这些规则最初可能看起来很受限制或令人困惑,但它们对于使 Hooks 良好运行至关重要。
详细解释
你可以在此页面上了解关于 Hooks 使用规则的更多信息:Hooks 使用规则。
💡 Building Your Own Hooks
有时,我们想在组件间重用一些状态的逻辑。以前,有两个流行的解决方案:高阶组件和 render props。现在,自定义 Hooks 也允许你这么做,并无需向组件树中添加更多组件层级。
在本页前面,我们介绍了一个 FriendStatus
组件,调用 useState
和 useEffect
Hooks 订阅朋友的在线状态。假设我们还希望在另一个组件中重用此订阅逻辑。
首先,我们将这个逻辑提取到一个名为 useFriendStatus
的自定义 Hook 中:
import { useState, useEffect } from 'react'; |
它接收 friendID
作为参数,并返回我们的朋友是否在线。
现在我们可以从两个组件中使用它:
function FriendStatus(props) { |
function FriendListItem(props) { |
这些组件的状态是完全独立的。Hooks 是重用已有状态逻辑的一种方式,而不是状态的本身。事实上,每次调用 Hook 都有一个完全隔离的状态–所以你甚至可以在一个组件中使用相同的自定义Hook 两次。
自定义 Hooks 更像是一种约定而非功能。如果函数的名称以“use”开头并且它调用了其他 Hooks,我们称之为自定义 Hook。useSomething
的命名约定使我们的 linter 插件能够在使用 Hooks 的代码中查找错误。
You can write custom Hooks that cover a wide range of use cases like form handling, animation, declarative subscriptions, timers, and probably many more we haven’t considered. We are excited to see what custom Hooks the React community will come up with.
你可以编写自定义 Hooks,涵盖更广泛的使用场景,如表单处理,动画,声明订阅,计时器,以及更多我们没有考虑过的。我们很期望看到 React 社区发布各种定制的 Hooks。
详细说明
你可以在此专题页面上关于自定义 Hook 的更多信息:创造你自己的 Hooks。
🔌 Other Hooks
你可能会发现一些不太常用的内置 Hooks 也很有用。例如, useContext
允许你不引入嵌套来订阅 React context:
function Example() { |
useReducer
允许你使用 reducer 管理复杂组件的内部状态:
function Todos() { |
详细说明
你可以在此页面上了解关于内置 Hooks 的更多信息:Hooks API 参考。
Next Steps
如果这些介绍对你来说太简单了,或者你想详细了解更多内容,可以阅读下一节,从 State Hook 的文档开始。
你还可以查看 Hooks API 参考 和 Hooks常见问题解答。
最后,不要错过介绍页,它解释了我们为什么要添加 Hooks 以及我们将如何开始将它们与类搭配使用 – 而不重写我们的应用程序。