简单说明一下,react hooks 是一个已经在提议中的新功能,预计会随着React 16.7.0一起发布。 /以上所述所有React均指ReactJS,下述会用React简称/
要明白什么是React Hooks,那可能先了解一下它的两个替代品HOC和FaCC/Render Props
HOC(Higher-Order Components),React高阶组件
如果我们有一个需要共享的状态,需要在多个组件之间传递。我们会怎么做? 或者说,当多个组件有公用的部分的时候,我们会选择怎么做?
例如:
代码语言:javascript复制// ComponentA
import React, { Component } from "react";
export default class ComponentA extends Component {
state = { toggle: false };
click = () => {
this.setState({ toggle: !this.state.toggle });
};
render() {
const { toggle } = this.state;
return (
<div className="App">
<button onClick={this.click}>Toggle Name</button>
{toggle && <div>ComponentA</div>}
</div>
);
}
}
复制代码
这里我们举一个极端的例子,让ComponentB和A做一样的事情
代码语言:javascript复制// ComponentB
export default class ComponentB extends Component {
state = { toggle: false };
click = () => {
this.setState({ toggle: !this.state.toggle });
};
render() {
const { toggle } = this.state;
return (
<div className="App">
<button onClick={this.click}>Toggle Name</button>
{toggle && <div>ComponentB</div>}
</div>
);
}
}
复制代码
可以看到代码重复的部分非常多,只有文字显示的不同而已。 这里就需要用到HOC了。
使用HOC之后,变成
代码语言:javascript复制// ComponentA
import React, { Component } from "react";
import HOC from "./HOC";
class ComponentA extends Component {
render() {
return <div>ComponentA</div>;
}
}
export default HOC(ComponentA);
复制代码
ComponentB同上。
这里HOC的写法就是提出共有的部分,接收一个Component进行渲染。
代码语言:javascript复制const HOC = WrapperComponent =>
class HOC extends Component {
state = { toggle: false };
click = () => {
this.setState({ toggle: !this.state.toggle });
};
render() {
const { toggle } = this.state;
return (
<div className="App">
<button onClick={this.click}>Toggle Name</button>
{toggle && <WrapperComponent />}
</div>
);
}
};
export default HOC;
复制代码
可以发现,让公用的部分提取了出去,并且让代码看起来更简单舒服了一些。每一个组件只需要关注自己内部的状态,而公有的部分以及共享状态的部分就交给HOC去解决。 这样不论再加多少个类似的Component,都无需大量的写重复代码了。
FaCC(Function as Child Component)
原理和HOC差不多,只是运用到了一个叫做 children的react props 可以讲代码简化成
代码语言:javascript复制//ComponentA
export default class ComponentA extends Component {
render() {
return <FaCC>{toggle => toggle && <div>ComponentA</div>}</FaCC>;
}
}
复制代码
代码语言:javascript复制//FACC
export default class FaCC extends Component {
state = { toggle: false };
click = () => {
this.setState({ toggle: !this.state.toggle });
};
render() {
const { toggle } = this.state;
return (
<div className="App">
<button onClick={this.click}>Toggle Name</button>
{this.props.children(toggle)}
</div>
);
}
}
复制代码
Render Props是用的一样的方法,只是换了别的属性,不用children而已
那么HOC们,还能做什么?
通过上述的行为,我们已经发现了,它们可以共用很多部分的代码。 如果再深入思考一下,就可以想到,在复杂的业务逻辑里面,如果发送同一个API请求的haul,我们不应该在每一个独立component里面发送一个请求。因为它们共享了同一个state,这样会造成资源的浪费。 我们将HOC的部分代码更改一下,例如:
代码语言:javascript复制const HOC = WrapperComponent =>
class HOC extends Component {
state = { toggle: false, data: {} };
fetchData = () => {
fetch("/api", params).then(response => {
const { data } = data;
this.setState(data);
});
};
componentDidMount(){
this.fetchData();
}
render() {
/*......*/
};
export default HOC;
复制代码
React Hooks
在Hooks里面利用它的Effect,可以让我们使用到和Component一样的部分生命周期。 关于ReactHooks的详细介绍,我会在别的文章进行详细描述。 在这里,我想进行的是React Hooks,HOC,FACC的比较。
那么如果想实现上述功能,React Hooks会怎么做呢?
代码语言:javascript复制// Hooks
import { useState, useEffect } from "react";
const useHooks = () => {
const [data, setData] = useState(null);
const fetchData = () => {
fetch("/api", params).then(response => {
const { data } = data;
setData(data);
});
};
// Effect,这里相当于componentDidMount
useEffect(() => {
fetchData();
});
return data;
};
export default useHooks;
复制代码
在Component中需要用到公用的这个data的时候,我们只需要这样做
代码语言:javascript复制 // 这一行便是调用data的方法了
const data = Hooks();
return <div>{data}</div>;
复制代码
ReactHooks的优点?
使用ReactHooks无需复杂的DOM结构。
使用HOC们,去除掉了重复应用的问题。 可是打开React Dev Tool,我们会发现,我们的DOM结构却也更复杂了。 从
变成
再到
更重要的原因是,我觉得ReactHooks写起来更加简单,易懂,易读。
我想通过上述的代码比对,不难得出这个结论。
试想一下,在一个庞大项目里面,广泛使用HOC们,会带来什么样的代码复杂度?
为什么我觉得React才是前端的未来
正如我在前文描述的那样,不论是HOC还是FACC/Render Props,都有自己的技术上手难度以及理解困难的地方。 但是React Hooks的出现解决了这些问题。
一定有人不赞同,不负责任的猜测大概原因如下
- 行业本身需要有一定的技术门槛,写法和理解的困难是个体本身的学习能力以及钻研程度的问题,框架不应该为此埋单。
- React hooks 本身从写法实现上来说,违背一些JS的规范和趋势,如纯函数。
我的解答如下
- 技术门槛不错,但是我觉得技术是用来改变生活的,而不是为了让部分人找到工作。就好比开车有职业赛车手,也有普通在道路上开车的司机。作为专业从事这个行业的人员来说,我们是应该钻研以及理解一门技术。但是,如果一个后端的同事,或者一个初创小团队,需要做一个这样的东西。我觉得,技术简洁好实现,对他们来说应该是一个吸引点。
- 很多库为了实现一些简洁的功能,都会出现这样或那样的“奇怪”写法,这点认同。但是,有时候是需要一些取舍。
而我认为目前前端框架里面,能察觉到用简单的方式来处理日趋复杂的业务,这件事的,Angular, Vue 都还没有做到。 Angular非常完整,但是学习曲线相对陡。 Vue正在面临整库重写。 只有React,用简单的方式来处理复杂业务,并且第三方库生态链非常庞大。
所以,我看好它。