Hook

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

  • 其实就是专门用于增强函数组件的功能的,使之尽可能的替代类组件而存在

  • 本质上是一个函数(use...),可挂载任何功能

  • 仅在函数组件体内生效

State Hook
  • useState(defaultState);

  • 参数为默认的 state

  • 返回一个长度为 2 的数组,第一项是 state 值,第二项为改变 state 值的函数,const [count, setCount] = useState(0);

  • 状态可以有多个

State Hook原理
  • 函数组件的首次调用以及后续更新都会直接调用use...函数

  • React 通过函数组件节点的状态表格来保存 state 值,使其不会在每次组件函数调用时都会被初始化

  • 首次调用函数组件时这些 state 值会被按顺序保存在状态表格中,每个 state 值都有一个固定且唯一的下标值,从 0 开始

  • 更新函数组件时,将会忽略默认 state 值,直接通过对应下标值找到状态表格中所保存的值

  • 这也是 React 解释说为什么使用 useState 而不是 createState 命名的原因

State Hook注意点
  • useState 不可写在代码块之中,例如判断,循环。因为这可能导致更新函数组件时,一些 useState 不被执行之类的混乱情况,从而导致下标值对应错误,state 被赋予不正确的值

  • useState 所返回的第二项函数,引用不会改变,节省内存

  • set...函数的执行会使函数组件重新渲染,也就是再次执行函数

    • 若调用改变 state 值的函数set...state 的值与之前的完全相同(使用Object.is判断),则不会导致重新渲染

    • 调用改变 state 值的函数 set... 会直接替换原先的值,而不是合并覆盖,所以要注意引用值的使用,可使用 ...展开

  • 函数组件内的强制刷新可使用 const [, forceUpdate] = useState({}); forceUpdate({}); 调用时发现对象地址不同,则会重新渲染该函数组件

  • 如果某些状态之间并没有什么必然的联系,我们应该将他们分开来写,而不是混合到一个 state

  • 和类组件相同,函数组件中的状态改变若是在 DOM 事件中则是异步的,这种情况下多次调用状态变化函数会被合并来提高效率

  • 若是想要在 DOM 事件中多次调用状态变化函数,可以传入一个函数作为参数

  • setCount(prevC => prevC + 1); setCount(prevC => prevC + 1);

  • 这些函数会在 DOM 事件结束时依次执行,前一个函数的返回值作为后一个函数的参数

Effect Hook
  • 用于在函数组件内处理副作用

  • useEffect(),该函数接收一个函数参数,函数内部就是我们要执行的副作用代码

副作用
  • ajax 请求,计时器,其他异步操作,更改真实 DOM 对象,本地存储,其他会对外部产生影响的操作
Effect Hook注意点
  • 副作用函数(useEffect的函数参数)的运行时间点,位于更改了真实 DOM 之后,且已经完成重新渲染,也就是用户已经看到了页面变化之后,所以是异步执行,不会阻塞

  • 而类组件中的 componentDidMount 以及 componentDidUpdate 的执行时间点位于更改了真实 DOM 之后,但还未重新渲染,也就是用户还未看到页面变化之前

  • useEffect 在一个函数组件内可多次使用,但不可写入代码块之中,例如判断,循环。与 useState 同理

  • 副作用函数可以有一个返回值,返回值必须为函数或默认的undefined,该函数作用为清理遗留的副作用,例如计时器,运行时间点位于下次副作用函数运行之前,所以首次渲染组件不会运行,useEffect 函数的第二个参数未变化时也不会运行,组件被销毁时一定会运行

  • useEffect 函数可接受第二个数组参数,数组中传入该副作用函数内的依赖数据

    • 当组件重新渲染后,只有依赖数据与上次不同时,才会再次执行副作用函数

    • 所以若使用空数组作为useEffect 函数的第二个参数,那么副作用函数仅在首次渲染结束后运行一次,清理函数也仅在卸载时运行一次

  • 副作用函数中,若使用了组件函数 AO 中的变量,则由于闭包的原因,会导致副作用函数中变量不会实时变化,而是使用所在的某次组件函数的调用时的变量

自定义Hook
  • 参考

  • 将一些常用的,多个组件都会使用的Hook功能,抽离出去写成一个函数,就叫做自定义Hook

  • 组件在使用自定义Hook时就等同于将自定义Hook函数中的代码拿出来放到该自定义Hook函数执行的地方

    • 所以自定义Hook中使用set...同样会使自定义Hook函数本身以及使用她的函数组件都重新执行一次

    • 并且执行顺序也是从函数组件开始,遇到自定义Hook执行就进入自定义Hook函数内部执行,执行结束返回新的值赋值给接收的变量,最后就是函数组件剩余的代码执行

  • 自定义Hook必须以use开头

  • 自定义Hook中的state始终是独立的,所以在两个组件中使用相同的 Hook 也不会共享 state

Context Hook
  • 参考

  • 用于函数组件更轻松的获取context

  • 在消费组件中

    • const myContext = useContext(MyContext);
Callback Hook
  • 参考

  • 返回一个仅根据依赖项变化而变化地址的函数,常用于给纯组件传递属性方法

Memo Hook
  • 参考

  • 返回第一个函数参数的返回值,仅在依赖项变化时才会再次执行第一个函数参数,返回一个新的值

  • 常用于高开销的计算操作

Ref Hook
  • 参考

  • 让函数组件重新执行时不会又重新创建一个新的ref

  • 也就是让每个函数组件对象拥有一个固定不变的ref

  • 通过.current来获取,不局限于获取dom元素或组件对象

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。