随着不久前 React@16.8.0 的发布,Hooks 也算是正式来到了幕前。我的以为对React来讲,Hooks 能够算是一个里程碑式的功能。本文不会详细介绍 Hooks,若是对 Hooks 还不是很了解的,能够先看下 Introducing Hooks。javascript
简单来讲 Hooks 带来了能够在 Function Components 使用 state 和其它 React 特性的能力。而这带来的第一个很直观的好处就是原来写的 Function Components 由于需求变更须要增长 state 时,不再须要重构成 Class Components 了(重构再也不是火葬场了)。html
我的认为 Hooks 带来的最大益处就是可以帮咱们更好地组织业务代码,提升代码复用率。咱们经过一个例子来讲明,假设有这么一个需求:「组件须要根据浏览器宽度的变化,来显示不一样的内容」。java
咱们先用 Class Component 来实现:react
export default class ResizeClassComponent extends React.Component {
constructor(props) {
super(props);
this.resizeHandler = null;
this.state = {
width: window.innerWidth,
}
}
componentDidMount() {
this.resizeHandler = () => {
this.setState({
width: window.innerWidth
})
}
window.addEventListener('resize', this.resizeHandler);
}
componentWillUnmount() {
window.removeEventListener('resize', this.resizeHandler);
}
render() {
const { width } = this.state;
return (
<div>width: {width}</div>
)
}
}
复制代码
目前来看没什么问题,可是若是说如今又有一个组件须要实现这个功能,同样的代码再写一遍?那若是有不少组件都须要这个功能呢?每次都写一遍确定不现实,有人会说用render props
或者高阶组件
来处理这个问题,那就让咱们来实现一下:git
// render props
class ResizeRenderProps extends React.Component {
constructor(props) {
super(props);
this.resizeHandler = null;
this.state = {
width: window.innerWidth,
}
}
componentDidMount() {
this.resizeHandler = () => {
this.setState({
width: window.innerWidth
})
}
window.addEventListener('resize', this.resizeHandler);
}
componentWillUnmount() {
window.removeEventListener('resize', this.resizeHandler);
}
render() {
return this.props.children(this.state.width);
}
}
export default class ResizeClassComponent extends React.Component {
render() {
return (
<ResizeRenderProps> {width => <div>width: {width}</div>} </ResizeRenderProps>
)
}
}
复制代码
// 高阶组件
function withResize(WrappedComponent) {
return class ResizeHoc extends React.Component {
constructor(props) {
super(props);
this.resizeHandler = null;
this.state = {
width: window.innerWidth,
}
}
componentDidMount() {
this.resizeHandler = () => {
this.setState({
width: window.innerWidth
})
}
window.addEventListener('resize', this.resizeHandler);
}
componentWillUnmount() {
window.removeEventListener('resize', this.resizeHandler);
}
render() {
return <WrappedComponent width={this.state.width} />; } } } export default withResize(class ResizeClassComponent extends React.Component { render() { return ( <div>width: {this.props.width}</div> ) } }) 复制代码
虽然实现了功能,可是两种方式都不可避免地对原来组件作了重构,而且增长了一个层级,若是用的多了就会致使「wrapper hell」,抛开这个不谈,render props
和高阶组件
自己自带的复杂度就不够友好。github
那么 Hooks 是怎么解决的呢?浏览器
import React, { useState, useEffect } from 'react';
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const resizeHandler = () => setWidth(window.innerWidth);
window.addEventListener('resize', resizeHandler);
return () => window.removeEventListener('resize', resizeHandler)
})
return width;
}
export default function ResizeHooks() {
const width = useWindowWidth();
return (
<div>width: {width}</div>
)
}
复制代码
是否是感受简单又清楚?只须要自定义一个 Hook(其实也就是一个普通的函数啦,只不过用了内置的几个Hook),使用的时候就像调用一个普通的函数同样,没有复杂的概念须要理解。正如前面所说,Hooks 能够帮助咱们组织代码,让相关性的代码都在一块,而不是像在 Class Components 里散落在各个生命周期函数中,贴个图方便理解:app
图片来源:twitter.com/prchdk/stat…函数
从图中能够发现逻辑相关的代码都被单独抽成了一个个 Hook,这意味着这部分有状态的逻辑(stateful logic)能够被复用,并且更容易理解。测试
稍微解释下什么叫「有状态的逻辑(stateful logic)」,这里的状态指的就是 React 的 state,对应的无状态的逻辑就是普通的函数啦。在 Hooks 以前,若是要复用这种有状态的逻辑,除了上述的 render props
和高阶组件
以外就没有别的更简单直接的办法了。而有了 Hooks 以后,这部分逻辑可以被单独抽离出,职责更明确,从而使复用更加简单,代码更加清晰,并且也更便于测试。
不知道我说的这些有没有引发你对 Hooks 的兴趣呢?其实从 React 官方的态度能够看出是比较倾向于 Hooks 的,或者说是 Function Components,虽说是不会移除掉 Class Components(要是移除了,估计就炸了吧),可是能够在项目中先小范围试用下嘛,相信我你会喜欢上它的!
前面写的有点分散,最后再总结一下 Hooks 带来的开发体验上的提高:
render props
和高阶组件
,提供了更简单直观复用有状态的逻辑(stateful logic)的方法有了 Hooks 以后,Function Components 再也不是「高级字符串模版」啦!😝
以上只是我我的对 React Hooks 的一些想法,若有不对之处,欢迎指正~~
扩展阅读: