# 1. React Hooks

Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数。Hook 不能在 class 组件中使用

# 1.1. Hook 使用规则

  • 只能在函数最外层调用 Hook。不可在循环、条件判断或者子函数中调用。
  • 只能在 React 的函数组件或自定义的 Hook 中调用 Hook。不要在其他 JavaScript 函数中调用。

可以使用eslint-plugin-react-hooks来检测,在 Webpack 中添加配置如下:

  "eslintConfig": {
    "extends": "react-app",
    "plugins": [
      "react-hooks"
    ],
    "rules": {
      "react-hooks/rules-of-hooks":"error"
    }
  },

# 1.2. Hook 如何把调用和组件联系起来的?

React 保持对当先渲染中的组件的追踪。多亏了 Hook 规范,我们得知 Hook 只会在 React 组件中被调用(或自定义 Hook —— 同样只会在 React 组件中被调用)。

每个组件内部都有一个「记忆单元格」列表。它们只不过是我们用来存储一些数据的 JavaScript 对象。当你用 useState() 调用一个 Hook 的时候,它会读取当前的单元格(或在首次渲染时将其初始化),然后把指针移动到下一个。这就是多个 useState() 调用会得到各自独立的本地 state 的原因。

# 1.3. 类组件的不足

  • 状态逻辑难以复用
    • 缺少复用机制
      • 不方便封装逻辑,使用渲染属性和高阶组件也有缺点
    • 渲染属性和高阶组件导致层级冗余
      • 无论是高阶组件还是渲染属性,都相当与在原来的组件之上增加了新的组件层次。尤其是在 Chrome 调试器上会看到为了服用逻辑而添加的狠多组件层级,显得十分臃肿。不仅是调试体验问题、也存在着运行性能的问题
  • 趋向复杂时难以维护
    • 生命周期函数函数混杂不相干逻辑
    • 相关逻辑代码经常会打散到不同生命周期中
  • this 指向困扰
    • 内联函数需要绑定 this, 否则每次渲染都创建一个箭头函数
    • 类成员函数不能保证 this

# 1.4. hooks 优势

  • 函数组件无类实例 this 问题
    • hooks 是函数组件环境,所有逻辑都在函数内部,没有实例化概念,无复杂的 this 问题
  • 自定义 Hook 函数方便复用状态逻辑
    • hooks 指的是在函数内部调用的特殊函数,我们可以自定义 hooks 函数,在 hooks 函数内部,依旧可以调用 useState 和 useEffect 等 hooks 函数。这样就可以非常高效的将可复用逻辑提取出来
  • 副作用的关注点分离
    • hooks 天生优化了副作用代码逻辑
      • 每个 useEffect 来实现一个逻辑,不同逻辑写在不同的 useEffect 中,比冗在同一生命周期中好很多
      • 以前副作用大都是写在生命函数周期中
    • 副作用:
      • 发送网络请求
      • 访问原始 DOM 元素
      • 访问本地存储
      • 绑定解绑事件