在 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-library
的 render
和 fireEvent
工具来执行此操作)。
例如,此页面中的计数器示例可以像这样进行测试:
代码语言: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"
}
}