乐趣区

Redux之深入理解StoreActionReducer

前面有一篇文章比较详细的介绍了 redux,那么这篇文章主要是对 redux 中的几个角色进行深入的理解。主要有以下几个部分:

  • store
  • action
  • reducer
  • combineReducers
  • bindActionCreators

理解 Store

const store = createStore(reducer)

store 中常用的三个方法:

  1. getState()- 获取 state 对象
  2. dispatch(action)- 当从 UI 上改变某个状态的时候,需要 dispatch 一个 action
  3. subscribe(listener)- 通知 UI, 做出对应的改变

理解 Action

一个 Action 其实是描述行为的数据结构,如一个 ToDoList 的应用结构。比如要增加一个 ToDoItem,用 action 去描述:

{
  type:'ADD_TODO',
  text:'Build my first Redux App'
}

理解 Reducer

那么怎么去更新之前的 ToDoList,这时候就需要 reduer,reducer 其实是一个纯函数(其输出结果只依赖于传入的参数)。这个函数一般接受两个参数:

  • state- 之前的状态
  • action

      function todoApp(state=initialState,action){switch(action.type){
           case ADD_TODO:
               return Object.assign({},state,{
                 todos:[
                   ...state.todos,
                   {
                       text:action.text,
                       completed:false
                   }
                 ]
              })
           break;
           default:
               return state
        }
     }
    
    

理解 combineReducers

我们知道一个 reducer 其实就是一个函数,如果你的应用中有多个 reducer 的话,那么如何将它们组合起来一起使用?这时候就需要 combineReducers 这个工具函数了。这个函数可以接受多个 reducer 作为参数,最终形成的是一个封装后的函数。这个封装后的函数其实也是一个 reducer.

import {combineReducers} from 'redux'
import todoApp from './todoApp'
import counter from './counter'

export default combineReducers({
    todoApp,
    counter
})

理解 bindActionCreators

这个方法其实也是一个工具函数,可以帮助我们去使用 action

function addTodoWithDispatch(text){
    const action = {
        type:ADD_TODO,
        text
    }
    dispatch(action)
}

以上代码表示定义 action 的同时进行 dispatch 的操作

dispatch(addTodo(text))
dispatch(completeTodo(text))

那么使用 bindCationCreators 来实现以上的操作就简便很多,如:

const boundAddTodo = text => dispatch(addTodo(text))
const boundCompleteTodo = text => dispatch(completeTodo(text))

最终演示代码如下:

PureRedux.js

import React from 'react'
import {createStore,bindActionCreators,combineReducers} from 'redux'
function run(){
    // init state
    const initialState = {count:0}

    //create a reducer
    const counter = (state=initialState,action) => {switch(action.type){
            case 'PLUS_ONE':
                return {count:state.count+1};
            case 'MINUS_ONE':
                return {count:state.count-1};
            case 'CUSTOM_COUNT':
                return{count:state.count+action.payload.count}     
            default:
                break;       
        }
        return state
    }

    const todoApp = (state={}) => state

    //create store
    const store = createStore(combineReducers({
        counter,
        todoApp
    }));

    //cation creator
    function flusOne(){return {type:'PLUS_ONE'}
    }

    function minusOne(){return {type:'MINUS_ONE'}
    }

    function customCount(count){return {type:'CUSTOM_COUNT',payload:{count}}
    }

    flusOne = bindActionCreators(flusOne,store.dispatch)

    store.subscribe(() => console.log(store.getState()))
    // store.dispatch(flusOne());
    flusOne();
    store.dispatch(minusOne())
    store.dispatch(customCount(5))
}

export default () => (
    <div>
        <button onClick={run}>
            Run
        </button>
        <p>
            -- 请打开控制台查看运行结果
        </p>
    </div>
)

App.js

import React from 'react'
import PureRedux from './PureRedux'
class App extends React.Component{render(){
        return(
            <div>
                <PureRedux></PureRedux>
            </div>
        )
    }
}

export default App

总结

  • 对于应用的全局状态进行管理,是在进行 web 开发中很重要的一定,这样可以让我们统一去做维护,像 VueJs 的 vuex,可以结合 React 使用的 Redux 等。
  • 在传统的 MVC 模式中,可能一个 view 对应多个 model,或是多个 view 对应一个 model,当应用变得复杂的时候,这样的管理是很乱其不易维护的,而 redux 则是利用一个外界仓库 (store),来对应用的状态进行统一管理(单向数据流),当用户操作 UI 想改变某个 state 的时候,必须通过 dispatch(action) 去操作,最后通过 store 对象的 subscribe 方法去进行 UI 的更新。
  • 当一个应用中有多个 reducer(纯函数,用来根据 action 改变 state)的时候,可以通过 redux 中的 combineReducers 来对多个 reducer 进行封装管理。
退出移动版