Hook 规则 – React

Hook 规则

Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。

Hook 本质就是 JavaScript 函数,但是在使用它时需要遵循两条规则。我们提供了一个 linter 插件来强制执行这些规则:

只在最顶层使用 Hook

不要在循环,条件或嵌套函数中调用 Hook, 确保总是在你的 React 函数的最顶层以及任何 return 之前调用他们。遵守这条规则,你就能确保 Hook 在每一次渲染中都按照同样的顺序被调用。这让 React 能够在多次的 useStateuseEffect 调用之间保持 hook 状态的正确。(如果你对此感到好奇,我们在下面会有更深入的解释。)

只在 React 函数中调用 Hook

**不要在普通的 JavaScript 函数中调用 Hook。**你可以:

  • ✅ 在 React 的函数组件中调用 Hook
  • ✅ 在自定义 Hook 中调用其他 Hook (我们将会在下一页 中学习这个。)

遵循此规则,确保组件的状态逻辑在代码中清晰可见。

ESLint 插件

我们发布了一个名为 eslint-plugin-react-hooks 的 ESLint 插件来强制执行这两条规则。如果你想尝试一下,可以将此插件添加到你的项目中:

我们打算后续版本默认添加此插件到 Create React App 及其他类似的工具包中。

npm install eslint-plugin-react-hooks --save-dev
1// 你的 ESLint 配置 2{ 3 "plugins": [ 4 // ... 5 "react-hooks" 6 ], 7 "rules": { 8 // ... 9 "react-hooks/rules-of-hooks": "error", // 检查 Hook 的规则 10 "react-hooks/exhaustive-deps": "warn" // 检查 effect 的依赖 11 } 12}

**现在你可以跳转到下一章节学习如何编写你自己的 Hook。**在本章节中,我们将继续解释这些规则背后的原因。

说明

正如我们之前学到的,我们可以在单个组件中使用多个 State Hook 或 Effect Hook

1function Form() { 2 // 1. Use the name state variable 3 const [name, setName] = useState('Mary'); 4 5 // 2. Use an effect for persisting the form 6 useEffect(function persistForm() { 7 localStorage.setItem('formData', name); 8 }); 9 10 // 3. Use the surname state variable 11 const [surname, setSurname] = useState('Poppins'); 12 13 // 4. Use an effect for updating the title 14 useEffect(function updateTitle() { 15 document.title = name + ' ' + surname; 16 }); 17 18 // ... 19}

那么 React 怎么知道哪个 state 对应哪个 useState?答案是 React 靠的是 Hook 调用的顺序。因为我们的示例中,Hook 的调用顺序在每次渲染中都是相同的,所以它能够正常工作:

1// ------------ 2// 首次渲染 3// ------------ 4useState('Mary') // 1. 使用 'Mary' 初始化变量名为 name 的 state 5useEffect(persistForm) // 2. 添加 effect 以保存 form 操作 6useState('Poppins') // 3. 使用 'Poppins' 初始化变量名为 surname 的 state 7useEffect(updateTitle) // 4. 添加 effect 以更新标题 8 9// ------------- 10// 二次渲染 11// ------------- 12useState('Mary') // 1. 读取变量名为 name 的 state(参数被忽略) 13useEffect(persistForm) // 2. 替换保存 form 的 effect 14useState('Poppins') // 3. 读取变量名为 surname 的 state(参数被忽略) 15useEffect(updateTitle) // 4. 替换更新标题的 effect 16 17// ...

只要 Hook 的调用顺序在多次渲染之间保持一致,React 就能正确地将内部 state 和对应的 Hook 进行关联。但如果我们将一个 Hook (例如 persistForm effect) 调用放到一个条件语句中会发生什么呢?

1 // 🔴 在条件语句中使用 Hook 违反第一条规则 2 if (name !== '') { 3 useEffect(function persistForm() { 4 localStorage.setItem('formData', name); 5 }); 6 }

在第一次渲染中 name !== '' 这个条件值为 true,所以我们会执行这个 Hook。但是下一次渲染时我们可能清空了表单,表达式值变为 false。此时的渲染会跳过该 Hook,Hook 的调用顺序发生了改变:

1useState('Mary') // 1. 读取变量名为 name 的 state(参数被忽略) 2// useEffect(persistForm) // 🔴 此 Hook 被忽略! 3useState('Poppins') // 🔴 2 (之前为 3)。读取变量名为 surname 的 state 失败 4useEffect(updateTitle) // 🔴 3 (之前为 4)。替换更新标题的 effect 失败

React 不知道第二个 useState 的 Hook 应该返回什么。React 会以为在该组件中第二个 Hook 的调用像上次的渲染一样,对应的是 persistForm 的 effect,但并非如此。从这里开始,后面的 Hook 调用都被提前执行,导致 bug 的产生。

**这就是为什么 Hook 需要在我们组件的最顶层调用。**如果我们想要有条件地执行一个 effect,可以将判断放到 Hook 的_内部_:

1 useEffect(function persistForm() { 2 // 👍 将条件判断放置在 effect 中 3 if (name !== '') { 4 localStorage.setItem('formData', name); 5 } 6 });

注意:如果使用了提供的 lint 插件,就无需担心此问题。 不过你现在知道了为什么 Hook 会这样工作,也知道了这个规则是为了避免什么问题。

下一步

最后,接下来会学习如何编写自定义 Hook!自定义 Hook 可以将 React 中提供的 Hook 组合到定制的 Hook 中,以复用不同组件之间常见的状态逻辑。

点赞
收藏

评论区

加载中...

相关推荐

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

React Hook丨用好这9个钩子,所向披靡

ReactHook指南什么是Hook?Hook是React16.8的新增特性。它可以让你在不编写class的情况下使用state以及其他的React特性。Hook本质上就是一个函数,它简洁了组件,有自己的状态管理,生命周期管理,状态共享。useStateuseEffectuseContextus

Hook 简介 – React

Hook简介_Hook_是React16.8的新增特性。它可以让你在不编写class的情况下使用state以及其他的React特性。importReact,{useState}from'react';functionExample(){//声明一个新的叫做“count”的sta

Hook 规则 – React

Hook规则_Hook_是React16.8的新增特性。它可以让你在不编写class的情况下使用state以及其他的React特性。Hook本质就是JavaScript函数,但是在使用它时需要遵循两条规则。我们提供了一个linter插件(https://www.npmjs.com/package/

Hook 概览 – React

Hook概览_Hook_是React16.8的新增特性。它可以让你在不编写class的情况下使用state以及其他的React特性。Hook是。本页面为有经验的React用户提供一个对Hook的概览。这是一个相当快速的概览,如果你有疑惑,可以参阅下面这样的黄色提示框。详细说明有关我们为什么要在Rea