介绍 Hooks(Introducing Hooks)

Hooks 是一项新功能提案,可让您在不编写类的情况下使用 state(状态) 和其他 React 功能。它们目前处于 React v16.7.0-alpha 中,并在 一个开放RFC 中进行讨论。

import { useState } from 'react';

function Example() {
  // 声明一个新的状态变量,我们将其称为 "count" 
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

这个新函数 useState 是我们将要学习的第一个 “Hook” ,但这个例子只是一个预告。 如果它没有意义,请不要担心!

你可以在 下一页 开始学习 Hooks。 在这个页面上,我们将继续解释为什么我们将 Hook 添加到 React 以及它们如何帮助您编写出色的应用程序。

视频介绍

在 React Conf 2018 上, Sophie Alpert 和 Dan Abramov 介绍了hook,接下来是 Ryan Florence,她展示了如何重构应用程序来使用Hooks。请看这里的视频:


没有重大变化

在我们继续之前,请注意 Hooks 是:

  • 完全是选择性加入。您可以在几个组件中尝试 Hooks ,而无需重写任何现有代码。但是如果你不想,你现在不必学习或使用 Hooks 。
  • 100%向后兼容。Hooks 不包含任何重大更改。
  • 现在可用。 Hook 目前处于 alpha 版本,我们希望在收到社区反馈后将它们包含在 React 16.7 中。

我们没计划从 React 中删除类。你可以在本页面底部阅读更多关于渐进式采用 Hook 的策略信息。

Hooks不会取代你对React概念的了解。相反,Hooks 为您已经知道的 React 概念提供了更直接的API:props,state,context,refs和lifecycle。正如我们稍后将展示的,Hooks还提供了一种新的强大方式来组合它们。

如果您只是想开始学习Hooks,请随意直接跳到下一页! 您还可以继续阅读此页面,详细了解我们为什么要添加Hooks,以及我们如何在不重写应用程序的情况下开始使用它们。

动机

Hook 解决了 React 中各种看似无关的问题,在过去五年时间我们在编写和维护数以万计的组件时遇到了这些问题。无论您是学习React,还是每天使用它,还是更喜欢使用具有类似组件模型的其他库,您都可能会发现其中的一些问题。

在组件之间重用有状态逻辑很困难

React并没有为组件提供一种可重复使用行为的方法(例如,将其关联到 store 里)。如果你已经使用了 React 一段时间,你可能会熟悉 render props(渲染属性)高阶组件的模式尝试解决这个问题。但是这些模式要求您在使用它们时重构组件,这可能很麻烦并且使代码更难以跟踪。如果你看一下 React DevTools 中典型的 React 应用程序,你可能会发现一个包含提供者,消费者,高阶组件,渲染属性和其他抽象层的组件所包裹起来的组件。虽然我们可以 在 DevTools 中过滤它们 ,但这会引出了一个更深层次的基本问题:React 需要一个更好的原语来共享有状态逻辑。

使用 Hook ,您可以从组件中提取有状态逻辑,以便可以独立测试并重用。Hooks 允许您在不更改组件层次结构的情况下重用有状态逻辑。 这样可以轻松地在许多组件个之间或与社区共享 Hooks 。

我们将在 构建你自己的 Hooks 中进行更多讨论。

复杂的组件变得难以理解

我们常常不得不维护一些组件,这些组件一开始很简单,但后来却变成了一堆难以管理的有状态逻辑和副作用。每个生命周期方法通常包含一组不相关的逻辑。例如,组件可能在componentDidMountcomponentDidUpdate中执行一些数据获取。然而,相同的 componentDidMount 方法可能还包含一些不相关的逻辑,它们设置事件监听器,并在 componentWillUnmount 中执行清理。一起更改的相互关联的代码会被分离,但是完全不相关的代码最终会组合在一个方法中。这很容易引入错误和不一致。

在许多情况下,将这些组件分解成更小的组件是不可能的,因为有状态逻辑到处都是。测试它们也很困难。这也是许多人喜欢将 React 与单独的状态管理库结合使用的原因之一。然而,这通常会引入太多的抽象,需要在不同的文件之间跳转,并且使得重用组件更加困难。

要解决这个问题,Hooks允许您根据相关内容(例如设置订阅或获取数据)将一个组件拆分为较小的函数,而不是基于生命周期方法强制拆分。您还可以选择使用 reducer 管理组件的本地state(状态),以使其更具可预测性。

我们将在 使用效果 Hook 中进行更多讨论。

人和机器都容易混淆的 类(class)

除了使代码重用和代码组织更加困难之外,我们发现 类(class) 可能是学习 React 的一大障碍。您必须了解 this 在 JavaScript 中是如何工作的, this 与多数语言中的工作方式有很大不同。您必须记住绑定事件处理程序。没有不稳定的 语法提议,代码非常冗长。人们可以很好地理解属性,状态和自上而下的数据流,但仍然很难与 类(class) 斗争。 React中的函数式和类组件之间的区别,以及何时使用每个组件,即使在经验丰富的React开发人员之间也存在分歧。

此外,React 已经推出了大约五年了,我们希望确保它在未来五年内保持相关性。正如SvelteAngularGlimmer和其他人所表明的那样,提前编译组件在未来具有很大的潜力。特别是在它不局限于模版的情况下。最近,我们一直在尝试使用Prepack 进行 组件折叠的尝试,并且已经看到了有希望的早期结果。但是,我们发现类组件可能会鼓励无意识的模式,使这些优化回退到较慢的路径。类(class)也为今天的工具提出了问题。例如,类不能很好地压缩,并且它们使得热更新加载变得片状和不可靠。我们希望提供一种 API,使代码更可能的留在可优化的路径上。

为了解决这些问题,Hooks 允许您在没有类的情况下使用更多 React 的功能。 从概念上讲,React 组件一直更接近函数。 Hooks 拥抱函数,但不会牺牲 React 的实际精神。 Hooks 提供了对命令式逃生舱的访问,并且不需要您学习复杂的函数式或反应式编程技术。

示例

Hooks 概述 是开始学习 Hook 的好地方。

采用逐步策略

TLDR: 没有从 React 中移除类的计划

我们知道 React 开发人员专注于发布产品,没有时间研究正在发布的每个新 API 。Hooks 非常新,在考虑学习或采用它们之前等待更多示例和教程可能会更好。

我们也理解为 React 添加新原语的标准非常高。对于好奇的读者,我们已经准备了一个详细的 RFC,其中包含更多细节的动机,并提供有关特定设计决策和相关现有技术的额外视角。

至关重要的是,Hooks与现有代码并行工作,因此您可以逐步采用它们。 我们正在分享这个实验性的 API ,以便从社区中那些有兴趣塑造 React 未来的人那里获得早期反馈 - 我们将在公开场合迭代 Hooks。

最后,没有急于迁移到 Hooks 。我们建议避免任何“重大改写”,特别是对于现有的复杂类组件。开始用钩子思考需要一点思维的转变。根据我们的经验,最好先在新的和非关键的组件中使用 Hooks ,并确保您的团队中的每个人都对它们感到满意。在您尝试 hook 之后,请随时给我们反馈,无论是积极的还是消极的。

我们打算让 Hooks 涵盖所有现有的类用例,但我们将在可预见的未来继续支持类组件。。在 Facebook,我们有数以万计用类编写的组件,显然我们没有要重写它们的计划。相反地,我们开始在新的代码中并行使用 Hook 和 类。

下一步

在本页的结尾,你应该大致了解 Hooks 正在解决的问题,但很多细节可能还不清楚。别担心!现在让我们进入下一页,我们通过示例开始学习 Hook。