Hooks核心02
新思想的开始很重要
如果已经习惯了类组件的开发,那么要做的,甚至是彻底忘掉那些生命周期方法。不要遇到一个需求,就映射到这个功能该在哪个生命周期中去做,然后又要去想原来的声明周期方法在函数组件中应该怎么用 Hooks 去实现。
正确的思路应该是遇到需求时,直接考虑在 Hooks 中去如何实现。
useState:让函数组件具有维持状态的能力
原则:state 中永远不要保存可以通过计算得到的值
- 通过 props 传递过来的值。
- 从 URL 中读到的值。
- 从 cookie、localStorage 中读取的值。
useEffect:执行副作用
什么是副作用?
通常来说,副作用是执行与当前结果无关的代码。比如说要修改函数外部的某个变量,要发起一个请求,等等。也就是说,在函数组件的当次执行过程中,useEffect 中代码的执行是不影响渲染出来的 UI 的。
useEffect 让我们能够在下面四种时机去执行一个回调函数产生副作用:
- 每次 render 后执行:不提供第二个依赖项参数。比如 useEffect(() => {})。
- 仅第一次 render 后执行:提供一个空数组作为依赖项。比如 useEffect(() => {}, [])。
- 第一次以及依赖项发生变化后执行:提供依赖项数组。比如 useEffect(() => {}, [deps])。
- 组件 unmount 后执行:返回一个回调函数。比如 useEffect() => { return () => {} }, [])。
理解 Hooks 的依赖
Hooks 提供了让你监听某个数据变化的能力。这个变化可能会触发组件的刷新,也可能是去创建一个副作用,又或者是刷新一个缓存。那么定义要监听哪些数据变化的机制,其实就是指定 Hooks 的依赖项。
定义依赖项的注意点:
- 依赖项中定义的变量一定是会在回调函数中用到的,否则声明依赖项其实是没有意义的。
- 依赖项一般是一个常量数组,而不是一个变量。因为一般在创建 callback 的时候,你其实非常清楚其中要用到哪些依赖项了。
- React 会使用浅比较来对比依赖项是否发生了变化,所以要特别注意数组或者对象类型。如果你是每次创建一个新对象,即使和之前的值是等价的,也会被认为是依赖项发生了变化。(每次重新渲染函数,依赖项的地址发生的变化)
掌握 Hooks 的使用规则
Hooks 本身作为纯粹的 JavaScript 函数,不是通过某个特殊的 API 去创建的,而是直接定义一个函数,所以需要遵循一定的规则才能正常的工作。
使用规则如下:
- 在 useEffect 的回调函数中使用的变量,都必须在依赖项中声明;
- Hooks 不能出现在条件语句或者循环中,也不能出现在 return 之后;
- Hooks 只能在函数组件或者自定义 Hooks 中使用。
class 组件就不能使用 hooks 了吗?
利用高阶组件的模式,将 Hooks 封装成高阶组件,从而让类组件使用。
import React from "react"
import { useWindowSize } from "../hooks/useWindowSize"
const withWindowSize = Component => {
return props => {
const windowSize = useWindowSize()
return <Component windowSize={windowSize} {...props} />
}
}
class MyComponent {
render() {
const { windowSize } = this.props
// ...
}
}
// 通过 withWindowSize 高阶组件给 MyComp 添加 windowSize 属性
export default withWindowSize(MyComponent)