渐进的状态管理
状态管理概述与技术选型
无论是
综上所述,笔者认为
渐进的状态管理
复杂单页应用的状态设计
Redux Really Do The Right Thing!Redux Always Do The Best Thing?
const initialState = {
users: [
{
name: "Dan"
},
{
name: "Michel"
}
]
};
// reducer
function users(state = initialState, action) {
switch (action.type) {
case "USER_ADD":
return { ...state, users: [...state.users, action.user] };
default:
return state;
}
}
// action
// { type: 'USER_ADD', user: user };
然后你需要在需要调用该
dispatch({ type: "USER_ADD", user: user });
笔者最近的两个项目中都使用了
- 必须使用基本对象与数组来描述应用状态
- 必须使用基本的对象来描述系统变化
- 必须使用纯函数来处理系统中的业务逻辑
而
笔者觉得,
了解下MobX

import {observable} from 'mobx';
export default class TodoModel {
store;
id;
@observable title;
@observable completed;
constructor(store, id, title, completed) {
this.store = store;
this.id = id;
this.title = title;
this.completed = completed;
}
... //还有一些功能函数
}
这里 @observable
注解标注某个变量为被观测值,一旦某个被观测的变量发生了变化,即可以触发观测值相对应的响应。在写好了模型类之后,我们需要编写
import { observable, computed, reaction } from 'mobx';
import TodoModel from '../models/TodoModel';
import * as Utils from '../utils';
export default class TodoStore {
@observable todos = [];
@computed
get activeTodoCount() {
return this.todos.reduce((sum, todo) => sum + (todo.completed ? 0 : 1), 0);
}
@computed
get completedCount() {
return this.todos.length - this.activeTodoCount;
}
subscribeServerToStore() {
reaction(
() => this.toJS(),
todos =>
fetch('/api/todos', {
method: 'post',
body: JSON.stringify({ todos }),
headers: new Headers({ 'Content-Type': 'application/json' })
})
);
}
subscribeLocalstorageToStore() {
reaction(
() => this.toJS(),
todos => localStorage.setItem('mobx-react-todomvc-todos', todos)
);
}
addTodo(title) {
this.todos.push(new TodoModel(this, Utils.uuid(), title, false));
}
toggleAll(checked) {
this.todos.forEach(todo => (todo.completed = checked));
}
clearCompleted() {
this.todos = this.todos.filter(todo => !todo.completed);
}
...
}
这里有使用
@observer
export default class TodoApp extends React.Component {
render() {
const { todoStore, viewStore } = this.props;
return (
<div>
<DevTool />
<header className="header">
<h1>todos</h1>
<TodoEntry todoStore={todoStore} />
</header>
<TodoOverview todoStore={todoStore} viewStore={viewStore} />
<TodoFooter todoStore={todoStore} viewStore={viewStore} />
</div>
);
}
componentDidMount() {
var viewStore = this.props.viewStore;
var router = Router({
"/": function() {
viewStore.todoFilter = ALL_TODOS;
},
"/active": function() {
viewStore.todoFilter = ACTIVE_TODOS;
},
"/completed": function() {
viewStore.todoFilter = COMPLETED_TODOS;
}
});
router.init("/");
}
}
TodoApp.propTypes = {
viewStore: React.PropTypes.object.isRequired,
todoStore: React.PropTypes.object.isRequired
};
我们需要状态管理吗?
笔者在我的前端之路这篇综述中提过,前端一直在从随意化到工程化的变革,而笔者认为的工程化的几个特征,即视图组件化、功能模块化与状态管理。笔者觉得,在构建前端项目,乃至于编写简单的

而当我们考量某个状态管理框架时,我们往往希望其能够提供以下的特征或者接口:
- 不同的组件之间能够共享状态。这一点应该算是将组件内状态提取到外部的重要原因之一,早期的
React 中如果你不同组件之间需要共享状态,只能一层一层地Props 传递或者通过公共父节点来传递。虽然现在React 引入了Context ,不过笔者认为其还是更适合于用作一些全局配置的传递。 - 状态能够在任意地方被访问,这是为了方便我们在纯粹的业务逻辑函数中也能够操作状态。
- 组件能够修改状态。
- 组件能够修改其他组件的状态。
High Order Component
笔者在
import { connect } from "react-redux";
import { bindActionCreators } from "redux";
function mapStateToProps(state, props) {
const { id } = props;
const user = state.users[id];
return {
user
};
}
function mapDispatchToProps(dispatch) {
return {
onUpdateUser: bindActionCreators(actions.updateUser, dispatch)
};
}
const UserProfileContainer = connect(
mapStateToProps,
mapDispatchToProps
)(UserProfile);
而类似的在
import { observer, inject } from "mobx-react";
const UserProfileContainer = inject("userStore")(
observer(({ id, userStore }) => {
return (
<UserProfile
user={userStore.getUser(id)}
onUpdateUser={userStore.updateUser}
/>
);
})
);
Immutable State Tree in Single Store
export default class SlidesStore {
// Observable history array
@observable history = Immutable.from([{
currentSlideIndex: 0,
slides: [{
// Default first slide
}]
}])
// Start state at the first entry in history
@observable historyIndex = 0;
}
addToHistory(snapshot) {
this.history = this.history.concat([Immutable.from(snapshot)]);
this.historyIndex += 1;
}
项目增长过程中的状态管理方案衍化
王国维先生说过人生有三个境界,我觉得根据项目的需求不同或者,。技术应该是为业务需求所服务,仅仅为了使用新的技术而罔顾实际的业务需求就是耍流氓。笔者在思索自己应该使用的状态管理框架时,有一个重要的考虑点就是项目尽可能地小代价的演进与迭代。譬如在立项之初,需求并不明确,功能逻辑尚不复杂的时候,我们可以直接从
原型| Local State
这个阶段我们可能直接将数据获取的函数放置到setState
函数存放在
// component
<button onClick={() => store.users.push(user)} />
这里的
项目增长| External State
随着项目逐渐复杂化,我们需要寻找专门的状态管理工具来进行外部状态的管理了
// component
<button onClick={() => store.addUser(user)} />
// store
@action addUser = (user) => {
this.users.push(user);
}
这个时候你也可以直接在组件内部修改状态,即还是使用第一个阶段的代码风格,直接操作
// root file
import { useStrict } from "mobx";
useStrict(true);
多人协作/ 严格规范/ 复杂交互:Redux
随着项目体量进一步的增加与参与者的增加,这时候使用声明式的
// reducer
(state, action) => newState;