在 React 的学习和开发中,如果 state (状态)变得复杂时(例如一个状态需要能够在多个 view 中使用和更新),使用 Redux 可以有效地管理 state,使 state tree 结构清晰,方便状态的更新和使用。当然,Redux 和 React 并没有什么关系。Redux 支持 React、Angular、Ember、jQuery 甚至纯 JavaScript。只是对我来说目前主要需要在 React 中使用,所以在这里和 React 联系起来便于理解记忆。数据流Action只是描述 state (状态)更新的动作,即“发生了什么”,并不更新 state。const ADD_TODO = ‘ADD_TODO’{ type: ADD_TODO, text: ‘Build my first Redux app’}type:必填,表示将要执行的动作,通常会被定义成字符串常量,尤其是大型项目。除了 type 外的其他字段:可选,自定义,通常可传相关参数。例如上面例子中的 text。Action 创建函数简单返回一个 Action:function addTodo(text) { return { type: ADD_TODO, text }}dispatch Action:dispatch(addTodo(text))// 或者创建一个 被绑定的 action 创建函数 来自动 dispatchconst boundAddTodo = text => dispatch(addTodo(text))boundAddTodo(text)帮助生成 Action 创建函数的库(对减少样板代码有帮助):redux-actionsredux-actReducer说明在发起 action 后 state 应该如何更新。是一个纯函数:只要传入参数相同,返回计算得到的下一个 state 就一定相同。(previousState, action) => newState注意,不能在 reducer 中执行的操作:修改传入的参数执行有副作用的操作,如 API 请求和路由跳转调用非纯函数,如 Date.now() 或 Math.random()import { combineReducers } from ‘redux’import { ADD_TODO, TOGGLE_TODO, SET_VISIBILITY_FILTER, VisibilityFilters} from ‘./actions’const { SHOW_ALL } = VisibilityFiltersfunction visibilityFilter(state = SHOW_ALL, action) { switch (action.type) { case SET_VISIBILITY_FILTER: return action.filter default: return state }}function todos(state = [], action) { switch (action.type) { case ADD_TODO: return [ …state, { text: action.text, completed: false } ] case TOGGLE_TODO: return state.map((todo, index) => { if (index === action.index) { return Object.assign({}, todo, { completed: !todo.completed }) } return todo }) default: return state }}const todoApp = combineReducers({ visibilityFilter, todos})export default todoAppStoreRedux 应用只有一个单一的 store。维持应用的 state;提供 getState() 方法获取 state;提供 dispatch(action) 方法更新 state;通过 subscribe(listener) 注册监听器;通过 subscribe(listener) 返回的函数注销监听器。import { createStore } from ‘redux’import todoApp from ‘./reducers’let store = createStore( todoApp, [preloadedState], // 可选,state 初始状态 enhancer)import { createStore, combineReducers, applyMiddleware, compose } from ‘redux’import thunk from ‘redux-thunk’import DevTools from ‘./containers/DevTools’import reducer from ‘../reducers/index’export default function configureStore() { const store = createStore( reducer, compose( applyMiddleware(thunk), DevTools.instrument() ) ); return store;}react-reduxconnect() 方法(mapStateToProps、mapDispatchToProps)替代 store.subscribe(),从 Redux state 树中读取部分数据,并通过 props 提供给要渲染的组件。import { bindActionCreators } from ‘redux’;import { connect } from ‘react-redux’;import * as actions from ‘./actions’;class App extends Component { handleAddTodo = () => { const { actions } = this.props; actions.addTodo(‘Create a new todo’); } render() { const { todos } = this.props; return ( <div> <Button onClick={this.handleAddTodo}>+</Button> <ul> {todos.map(todo => ( <Todo key={todo.id} {…todo} /> ))} </ul> </div> ); }}function mapStateToProps(state) { return { todos: state.todos };}function mapDispatchToProps(dispatch) { return { actions: bindActionCreators({ addTodo: actions.addTodo }, dispatch) }}export default connect( mapStateToProps, mapDispatchToProps)(App);Provider 组件import React from ‘react’import { render } from ‘react-dom’import { Provider } from ‘react-redux’import configureStore from ‘./store/configureStore’import App from ‘./components/App’render( <Provider store={configureStore()}> <App /> </Provider>, document.getElementById(‘root’)API 请求一般情况下,每个 API 请求都需要 dispatch 至少三种 action:通知 reducer 请求开始的 action { type: ‘FETCH_POSTS_REQUEST’ }reducer 可能会 {…state, isFetching: true}一种通知 reducer 请求成功的 action { type: ‘FETCH_POSTS_SUCCESS’, response: { … } }reducer 可能会 {…state, isFetching: false, data: action.response}一种通知 reducer 请求失败的 action { type: ‘FETCH_POSTS_FAILURE’, error: ‘Oops’ }reducer 可能会 {…state, isFetching: false, error: action.error}使用 middleware 中间件实现网络请求:redux-thunkredux-sagaredux-thunk通过使用指定的 middleware,action 创建函数除了返回 action 对象外还可以返回函数。这时,这个 action 创建函数就成为了 thunk。路由跳转(react-router)参考资料:Redux 中文文档React Native Training