React v16.8: The One With Hooks

2019-10-08 12:31:41 浏览数 (1)

在 React 16.8 中,React Hook 稳定版本发布使用了!

什么是 Hook? {#what-are-hooks}

Hook 可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性,你也可以自定义 Hook 来在组件之间共享可重用的状态逻辑。

如果你以前从未听说过 Hook,你可能会对这些资源感兴趣:

 Hook 简介 解释了为什么我们要添加 Hook 到 React。  Hook 概览是对内置 Hook 的快速概述。  自定义 Hook 演示了利用自定义 Hook 重用代码。  了解 React Hook 探索 Hook 开启的新可能性。 * useHooks.com 展示了社区维护的 Hook 技巧和演示。

你不必现在就去学习 Hook。 Hook 没有任何破坏性改动,我们没有计划从 React 中移除 class。Hook FAQ 描述了 Hook 的渐进策略。

没有大的重写 {#no-big-rewrites}

我们不建议你在一夜之间重写现有的应用程序来使用 Hook。相反,你可以尝试在一些新的组件中使用 Hook,让我们知道你的想法。使用 Hook 的代码将与使用 class 的现有代码一起工作。

我今天可以使用 Hook 吗? {#can-i-use-hooks-today}

当然可以!从 16.8.0 开始,React 包含了稳定的 React Hook 实现:

 React DOM  React DOM 服务器  React 测试渲染器  React 浅渲染器

请注意,要启用 Hook,所有的 React 包必须是 16.8.0 或更高的版本。如果忘记更新,如:React DOM,Hook 将不起作用。

React Native 将在 0.59 版本中支持 Hook

工具支持 {#tooling-support}

React 开发者工具现在支持 React Hook。React 最新的 Flow 和 TypeScript 定义也支持 React Hook。我们强烈建议启用一个新的名为 eslint-plugin-react-hooks 的 lint 规则来执行使用 Hook 的最佳实践。它将很快被默认包含在 Create React App。

下一步是什么 {#whats-next}

我们在最近发布的 React Roadmap 中描述了下个月的计划。

请注意,React Hook 尚未涵盖 class 的所有用例,但它们非常接近。目前,只有 getSnapshotBeforeUpdate()  和 componentDidCatch() 方法没有等价的 Hook API,这些生命周期相对少见。如果需要,你应该能够在编写的大多数新代码中使用 Hook。

即使 Hook 在 alpha 版时,React 社区也创建了许多使用 Hook 有趣的示例和技巧,如:动画,表单,订阅,与其他库集成等等。我们对 Hook 感到非常兴奋,因为它们使代码更容易重用,帮助你以更简单的方式编写组件并获得更大的用户体验。 我们迫不及待想看到你下一步将创建什么!

测试 Hook {#testing-hooks}

我们在此版本中添加了一个名为 ReactTestUtils.act() 的新API。 它可以确保你测试中的行为与浏览器中的行为更接近。 我们建议将所有代码渲染和触发对组件的更新,包装到 act() 调用中。 测试库也可以使用它包装 API(例如,react-testing-libraryrenderfireEvent 工具来执行此操作)。

例如,此页面中的计数器示例可以像这样进行测试:

代码语言:txt复制
import React from 'react';
import ReactDOM from 'react-dom';
import { act } from 'react-dom/test-utils';
import Counter from './Counter';

let container;

beforeEach(() => {
  container = document.createElement('div');
  document.body.appendChild(container);
});

afterEach(() => {
  document.body.removeChild(container);
  container = null;
});

it('能渲染并更新计数器', () => {
  // 测试第一次渲染和效果
  act(() => {
    ReactDOM.render(<Counter />, container);
  });
  const button = container.querySelector('button');
  const label = container.querySelector('p');
  expect(label.textContent).toBe('你点击了 0 次');
  expect(document.title).toBe('你点击了 0 次');

  // 测试第二次渲染和效果
  act(() => {
    button.dispatchEvent(new MouseEvent('click', {bubbles: true}));
  });
  expect(label.textContent).toBe('你点击了 1 次');
  expect(document.title).toBe('你点击了 1 次');
});

act() 的调用也会刷新其中的效果。

如果你需要测试一个自定义的 Hook,你可以创建一个使用 Hook 的组件,然后再测试你写的组件。

为了减少样板代码,我们建议使用 react-testing-library,它旨在鼓励编写像最终用户那样使用组件的测试。

感谢 {#thanks}

我们想感谢在 Hooks RFC 上发表评论分享反馈意见的每个人。 我们已阅读了所有的评论并根据这些评论对最终 API 进行了一些调整。

安装 {#installation}

React {#react}

React v16.8.0 在 npm 注册表中可用。

使用 Yarn 安装 React 16,请运行:

代码语言:txt复制
yarn add react@^16.8.0 react-dom@^16.8.0

使用 npm 安装 React 16,请运行:

代码语言:txt复制
npm install --save react@^16.8.0 react-dom@^16.8.0

我们还通过 CDN 提供 React 的 UMD 构建:

代码语言:txt复制
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>

参考文档详细安装说明.

React Hook 的 ESLint 插件 {#eslint-plugin-for-react-hooks}

注意

如上所述,我们强烈建议使用 eslint-plugin-react-hooks lint 规则。

如果你使用 Create React App,而不是手动配置 ESLint,则可以等待下一个版本的react-scripts,它很快就会出来,并将包含此规则。

假设你已经安装了 ESLint,请运行:

代码语言:txt复制
npm
npm install eslint-plugin-react-hooks --save-dev

yarn
yarn add eslint-plugin-react-hooks --dev

然后将其添加到你的 ESLint 配置中:

代码语言:txt复制
{
  "plugins": [
    // ...
    "react-hooks"
  ],
  "rules": {
    // ...
    "react-hooks/rules-of-hooks": "error"
  }
}

0 人点赞