redux 是独立的,react可以引入它来解决状态管理的问题,和 vuex 在 vue 中起的作用一样 
redux 的具体过程是这样的,如下图:

步骤:
安装redux:
npm install redux –save
                        
这次依然用 Todolist 举例
页面如下:

新建 store 文件夹
处理状态的东西放到这个文件夹下,目录如下:

getState 获取 store 中的值
todoList.js:
1 2 3 4
   | import React, { Component } from 'react'; import store from '../store';   
  state = store.getState()
  | 
 
                            
通过 dispatch 改变 store 中的值
todoList.js:
1 2 3 4 5 6 7 8 9 10 11 12 13
   | import React, { Component } from 'react'; import store from '../store';   
  <input value={ this.state.inpVal } onChange={ this.handleChange }></input>
 
   handleChange = (e) => {     const action = {       type: 'CHANGE_INPUT_VAL',       value: e.target.value     }     store.dispatch(action);   }
  | 
 
                            
reducer 中定义如何去改变 store 中的值
store/index.js, 通过引入 redux 中的 createStore 来创建一个 store
1 2 3 4 5 6 7 8 9 10
   | import { createStore } from 'redux'; import reducer from './reducer';
  const store = createStore(   reducer,   window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() );
 
  export default store;
  | 
 
store/reducer.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   | const initState = {   inpVal: '',   list: ['蓝天', '白云', '阳光', '大海'] }
 
  export default (state=initState, action) => {   const newState = JSON.parse( JSON.stringify(state));
    switch (action.type) {     case 'CHANGE_INPUT_VAL':       newState.inpVal = action.value;       return newState;     case 'ADD_TODO_ITEM':       newState.list.push(action.value);       newState.inpVal = '';       return newState;     case 'DELETE_TODO_ITEM':       newState.list.splice(action.index, 1);       return newState;   }
    return state; }
  | 
 
                
subscribe  监控 store 中值的变化
todoList.js:
1 2 3 4 5 6 7
   | componentDidMount () {    store.subscribe(this.handleStoreChange);    }
  handleStoreChange = () => {    this.setState(store.getState()); }
  | 
 
                
通过 redux 管理状态的过程基本实现了,todoList.js 总和起来就是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
   | import React, { Component } from 'react'; import store from '../store';
  class c extends Component {
    state = store.getState()
    componentDidMount () {     store.subscribe(this.handleStoreChange);   }
    render () {     return (       <>         <div>           <input value={ this.state.inpVal } onChange={ this.handleChange }></input>           <button onClick={ this.handleAdd }>添加</button>         </div>         <ul>           {             this.state.list.map( (item, index) => (               <li key={item + index}>                 { item }                 <button onClick={ ()=>{ this.handleDelete(index) } }>X</button>               </li>             ))           }         </ul>       </>     )   }
    handleChange = (e) => {     const action = {       type: 'CHANGE_INPUT_VAL',       value: e.target.value     }     store.dispatch(action);   }
    handleAdd = () => {     const action = {       type: 'ADD_TODO_ITEM',       value: this.state.inpVal     }     store.dispatch( action );   }
    handleDelete = (index) => {     const action = {       type: 'DELETE_TODO_ITEM',       index     }     store.dispatch(action);   }
    handleStoreChange = () => {     this.setState(store.getState());   } }
  export default c;
  | 
 
但 action 这样放在组件中若是出错了也不太好找,所以把它整合起来放在一个文件夹中, 所以下面几个都是整理代码
                        
action 抽离成一个组件
在 store 中整合 actionTypes,并把需要的 action 导出,在这样在其他组件中直接调用就行了
store/actionTypes.js : 
1 2 3 4
   | export const CHANGE_INPUT_VAL = 'CHANGE_INPUT_VAL'; export const ADD_TODO_ITEM = 'ADD_TODO_ITEM'; export const DELETE_TODO_ITEM = 'DELETE_TODO_ITEM'; export const COUNT_ADD = 'COUNT_ADD';
   | 
 
store/actionCreators.js : 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
   | import * as Types from './actionTypes';
  export const getTodoChangeInputValAction = (value) => {   return {     type: Types.CHANGE_INPUT_VAL,     value   } }
  export const getTodoAddItemAction = (value) => {   return {     type: Types.ADD_TODO_ITEM,     value   } }
  export const getTodoDeleteItemAction = (index) => {   return {     type: Types.DELETE_TODO_ITEM,     index   } }
 
  export const getCountAddAction = (n) => {   return {     type: Types.COUNT_ADD,     n   } }
   | 
 
在 todoList.js 中直接使用 actionCreators:
1 2 3 4 5 6 7 8 9 10 11 12 13
   | import React, { Component } from 'react'; import store from '../store'; import * as Actions from '../store/actionCreators';
    handleChange = (e) => {     const action = Actions.getTodoChangeInputValAction(e.target.value);     store.dispatch(action);   }
    handleAdd = () => {     const action = Actions.getTodoAddItemAction( this.state.inpVal );     store.dispatch( action );   }
  | 
 
                        
抽离 reducer
现在 这个页面有两个小功能,一个是 todolist,一个是counter ,但他们的 reducer 都是写在一起的,所以这次把它们两个抽离出来,目录结构具体如下:

其中,store/reducer/counter.js : 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
   | import * as Types from '../actionTypes';
  const initState = {   count: 0 }
 
  export default (state=initState, action) => {   const newState = JSON.parse( JSON.stringify(state));
    switch (action.type) {     case Types.COUNT_ADD:       newState.count = newState.count + action.n;       return newState;   }
    return state; }
   | 
 
store/reducer/todoList.js : 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
   | import * as Types from '../actionTypes';
  const initState = {   inpVal: '',   list: ['蓝天', '白云', '阳光', '大海'] }
  export default (state=initState, action) => {   const newState = JSON.parse( JSON.stringify(state));
    switch (action.type) {     case Types.CHANGE_INPUT_VAL:       newState.inpVal = action.value;       return newState;
      case Types.ADD_TODO_ITEM:       newState.list.push(action.value);       newState.inpVal = '';       return newState;
      case Types.DELETE_TODO_ITEM:       newState.list.splice(action.index, 1);       return newState;
    }
    return state; }
   | 
 
store/reducer/index.js , 我们用 redux 中的 combineReducers ,把两个文件中的 actionCreators整合在一起:
1 2 3 4 5 6 7 8
   | import { combineReducers } from 'redux'; import todoList from './todoList'; import counter from './counter';
  export default combineReducers({   todoList,   counter })
  | 
 
reducer整合后使用的函数名有没有变化,在 component/counter.js :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
   | import React, { Component } from 'react'; import store from '../store'; import { getCountAddAction } from '../store/actions/counter';
  class c extends Component {
    state = store.getState().counter
    componentDidMount () {     store.subscribe(()=>{       this.setState(store.getState().counter)     })   }
    render () {     return (       <div>         { this.state.count }         <button onClick={ this.handleClick }>add</button>       </div>     )   }
    handleClick = () => {     const action = getCountAddAction(3);     store.dispatch(action);   } }
  export default c;
  |