React 基础巩固(四十二)——React Hooks的介绍
一、为什么需要Hook?
Hook 是 React 16.8 的新增特性,它可以让我们在不编写class的情况下使用state以及其他的React特性(比如生命周期)。
class组件 VS 函数式组件:
class的优势:
- class组件可以定义自己的state,用来保存组件自己内部的状态;而函数式组件不可以,因为函数每次调用都会产生新的临时变量。
- class组件有自己的生命周期,我们可以在对应的生命周期中完成自己的逻辑。比如在componentDidMount中发送网络请求,并且该生命周期函数只会执行一次。如果在函数中发送网络请求,意味着每次重新渲染都会重新发送一次网络请求。
- class组件可以在状态改变时只会重新执行render函数以及我们希望重新调用的生命周期函数componentDidUpdate等;而函数式组件在重新渲染时,整个函数都会被执行,似乎没有什么地方可以只让它们调用一次。
class的劣势:
-
组件变得日益复杂
- 随着业务的增多,class组件会变得越来越复杂;
- 比如componentDidMount中,可能就会包含大量的逻辑代码:包括网络请求、一些事件的监听(还需要在componentWillUnmount中移除);
- 而对于这样的class实际上非常难以拆分:因为它们的逻辑往往混在一起,强行拆分反而会造成过度设计,增加代码的复杂度;
-
难以理解的class
- 在class中,我们必须搞清楚this的指向到底是谁,所以需要花很多的精力去学习this,非常麻烦;
-
组件复用状态困难
- 复用状态需要通过高阶组件;
- 或者类似于Provider、Consumer来共享一些状态,但是多次使用Consumer时,我们的代码就会存在很多嵌套;
Hook的优势:
- 解决问题:在不编写class的情况下使用state以及其他的React特性,由此延伸出非常多的用法来解决上述的问题。
- 完美兼容:基本可以代替我们之前所有使用class组件的地方,它完全向下兼容,可以渐进式的来使用它。
二、类组件和结合Hook的函数组件的对比
-
用类组件实现一个计数器
import React, { PureComponent } from "react"; export class CounterClass extends PureComponent { constructor(props) { super(props); this.state = { counter: 0, }; } increment() { this.setState({ counter: this.state.counter + 1, }); } decrement() { this.setState({ counter: this.state.counter - 1, }); } render() { const { counter } = this.state; return ( <div> <h2>当前计数:{counter}</h2> <button onClick={(e) => this.increment()}>+1</button> <button onClick={(e) => this.decrement()}>-1</button> </div> ); } } export default CounterClass;
-
用Hook+函数组件的方式实现一个计数器
import { memo, useState } from "react"; function CounterHook(props) { const [counter, setCounter] = useState(0); return ( <div> <h2>当前计数:{counter}</h2> <button onClick={(e) => setCounter(counter + 1)}>+1</button> <button onClick={(e) => setCounter(counter - 1)}>-1</button> </div> ); } export default memo(CounterHook);
-
对比结果
两者虽然都能实现相同的计数器效果,但是从上文的代码量来看,利用Hook+函数组件的方式,代码更简洁,使用更方便,并且不用考虑this的相关问题!这就是Hook带来的历史性变革!