人们总是在自己真的需要redux之前,就选用redux。大家的出发点可能是“就算我现在不需要它,为了项目以后的可扩展性,我还是要用它”。然而之后开发上手写代码了,才发现不便之处:“为什么我实现一个简单的功能就需要加三个文件?”
人们将这些痛苦归咎于Redux,React,函数式编程,不可变性等。产生这种想法挺正常的,因为大家自然而然就会把Redux和其他的不需要“模板”来更新state的方法相对比,从而得出Redux更复杂的结论。从某种程度上说,redux的确就是这样的,它的设计就是这样的。
Redux的确有很多好处,但是它也有很严格的限制:
必须用对象和数组来描述应用state
必须用简单对象来描述系统的变化
必须用纯函数来描述处理变化的逻辑
事实上,不用redux的话,无论用不用react,构建应用程序都不需要遵从这些限制。而这些都是非常严格的限制,所以哪怕只在程序的一部分中用到,也值得仔细考量,真的有充分的理由这么做吗。
对我来说,这些限制很有用——下面这些功能都在这些限制的帮助下构建的:
- 将state存在本地,从而能关闭页面后再打开时恢复state链接
- 服务器将state放在html中发送给客户端,从而在此state基础上打开页面链接
- 触发bug时将用户action序列化,并获取state快照,用以发送bug报告以便于开发重现bug链接
- 通过网络传递action对象以实现协作环境,而不用复杂的代码修改链接
- 实现撤销功能及action实现乐观更新(即页面ui先变,再根据服务器返回结果更改ui,出错的话回滚),而不用复杂的代码修改链接
- 在state记录内切换,当代码变动时依据action历史计算当前state链接
- 为开发工具提供完整的检查和控制功能,便于开发为自家程序构建自定义工具链接
- 提供重用了大部分业务逻辑的可替代UI 链接
然而如果你只是刚学React,不要把Redux作为你的首选。
最后,其实你可以参考redux的想法而不一定真的要用redux实现。比如一个具有本地state的react组件:
import React, { Component } from 'react';
class Counter extends Component {
state = { value: 0 };
increment = () => {
this.setState(prevState => ({
value: prevState.value + 1
}));
};
decrement = () => {
this.setState(prevState => ({
value: prevState.value - 1
}));
};
render() {
return (
<div>
{ this.state.value }
<button onClick = { this.increment }> + </button>
<
button onClick = { this.decrement }> - </button>
</div>
)
}
}
这样写就挺好的,还能复用。本地 state表现也良好。
redux提供的折衷是将 “发生了什么” 和 “如何变化” 解耦。
那么是不是事情永远会表现得这么完美呢,并不,这只是个折衷。
举个栗子,我们可以从我们的组件中提取一个reducer:
import React, { Component } from 'react';
const counter = (state = { value: 0 }, action) => {
switch (action.type) {
case 'INCREMENT':
return { value: state.value + 1 };
case 'DECREMENT':
return { value: state.value - 1 };
default:
return state;
}
}
class Counter extends Component {
state = counter(undefined, {});
dispatch(action) {
this.setState(prevState => counter(prevState, action));
}
increment = () => {
this.dispatch({ type: 'INCREMENT' });
};
decrement = () => {
this.dispatch({ type: 'DECREMENT' });
};
render() {
return (
<div> { this.state.value }
<button onClick = { this.increment }> + </button>
<button onClick = { this.decrement } > - </button>
</div>
)
}
}
注意我们如何在不运行npm install真正安装的情况下使用redux。是不是很神奇?
当然了,你不一定会对你的带state的组件这么干。除非你明知从中能获取什么益处。
Redux Library只是一个帮助将reducers绑定到全局存储上去的工具而已,如何使用redux全凭个人。
最主要的还是,在决定使用之前,想清楚能获得的收益。