这是我参与「第五届青训营 」笔记创作活动的第 7 天
为什么需要Hook
Hook 是 React 16.8 的新增特性,它可以让我们在不编写class的情况下使用state以及其他的React特性(比如生命周期)。
class组件相对于函数式组件有什么优势?
-
class组件可以定义自己的state,用来保存组件自己内部的状态;函数式组件不可以,因为函数每次调用都会产生新的临时变量
-
class组件有自己的生命周期,可以在对应的生命周期中完成自己的逻辑;在hooks之前,如果在函数式组件中发送网络请求,意味着每次重新渲染都会重新发送一次网络请求
-
class组件可以在状态改变时只重新执行render函数以及生命周期函数,而函数式组件在重新渲染时,整个函数都会被执行
Class组件存在的问题
复杂组件变得难以理解:
随着业务的增多,class组件会变得越来越复杂, 比如componentDidMount中,可能就会包含大量的逻辑代码:
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>
);
}
}
包括网络请求、一些事件的监听(还需要在componentWillUnmount 中移除),而这样的class实际上非常难以拆分:因为它们的逻辑往往混在一起,强行拆分反而会造成过度设计,增加代码的复杂度。
组件复用状态很难:
为了实现一些状态的复用通常需要使用高阶组件
- redux中connect或react-router中的withRouter,这些高阶组件设计的目的就是为了状态的复用
- 当使用Provider、Consumer来共享一些状态时,多次使用Consumer,代码就会存在很多嵌套
- 这些代码不管是编写和设计上来说,都非常困难
Hook的出现
Hook的出现,可以解决上面提到的这些问题
function CounterHook(props) {
const [counter, setCounter] = useState(0);
const [name] = useState("why");
console.log(name);
return (
<div>
<h2>当前计数: {counter}</h2>
<button onClick={(e) => setCounter(counter + 1)}>+1</button>
<button onClick={(e) => setCounter(counter - 1)}>-1</button>
</div>
);
}
简单总结一下hooks:
它可以让我们在不编写class的情况下使用state以及其他的React特性,同时,可以由此延伸出非常多的用法,来解决上面提到的问题
Hook的使用场景:
Hook的出现基本可以代替所有使用class组件的地方,如果是一个旧的项目,并不需要直接将所有的代码重构为Hooks,因为Hooks完全向下兼容,可以渐进式的来使用它,但Hook只能在函数组件中使用,不能在类组件,或函数组件之外的地方使用
Hook 是:
-
完全可选的:你无需重写任何已有代码就可以在一些组件中尝试 Hook。但是如果你不想,你不必现在就去学习或使用 Hook。
-
100% 向后兼容的:Hook 不包含任何破坏性改动。
-
现在可用:Hook 已发布于 v16.8.0。
总结
Hook 就是 JavaScript 函数,这个函数可以帮助你 钩入(hook into) React State以及生命周期等特性。
但是使用它会有两个额外的规则:
- 只能在函数最外层调用 Hook。不要在循环、条件判断或者子函数中调用。
- 只能在 React 的函数组件中调用 Hook。不要在其他 JavaScript 函数中调用
可以看到:
函数式组件结合hooks能让整个代码变得非常简洁,并且也不用考虑this相关的问题