react+redux项目如何对state进行初始化

最近在学习redux,对照着官网的示例学习,总有些不明白的地方,所以研究了一下redux源码,主要针对combineReducers、createStore进行分析

具体执行函数请参照test.js,可将该文中的所有内容直接拷贝到Babel中,通过打印出的内容了解执行逻辑。

redux的工作原理:
1. actions: action 内必须使用一个字符串类型的 type 字段来表示将要执行的动作,一般情况下,我们通过Action创建函数来生成action,如function addTodo = (text) => ({type: ADD_TODO, text});
2. reducers: 指明应用如何更新state。reducer就是一个纯函数,接收旧的state和action,返回新的state。通过combinReducers({reducer1, reducer2})将所有的reducer进行合并,返回一个combination(state, action)方法
3. store:通过createStore(reducer)创建store,该store对state进行了初始化,store有以下职责:

维持应用的state;
提供getState()方法获取state;
提供dispatch(action)方法更新state;
通过subscribe(listener)注册监听器;
通过subscribe(listener)返回的函数注销监听器。

1. reducers

每个传入combineReducers的 reducer都需要满足以下规则:
1. 所有未匹配到的action,必须把它接收到的第一个参数也就是那个state原封不动返回。
2. 永远不能返回undefined。当过早return时非常容易犯这个错误,为了避免错误扩散,遇到这种情况时 combineReducers会抛出异常。
3. 如果传入的state是undefined, 一定要返回对应reducer的初始state。根据上一条规则,初始state禁止使用undefined。使用ES6的默认参数值语法来设置初始state很容易,但你也可以手动检查第一个参数是否为undefined

在reducer里不能做如下操作:
1. 修改传入参数
2. 执行有副作用的操作,如API请求和路由跳转
3. 调用非纯函数,如Date.now()或Math.random()

  //reducer1
  const selectedReddit = (state = 'frontend', action) => {
    switch(action.type){
      case 'SELECT_REDDIT':
        return action.reddit
      default
        return state
    }
  }

  //reducer2
  const postsByReddit = (state = { }, action) => {

    switch (action.type) {
      case INVALIDATE_REDDIT:
      case RECEIVE_POSTS:
      case REQUEST_POSTS:
        return {
          ...state,
          //doSomething
        }
      default:
        return state
    }
  }


通过combineReducers可以将多个reducer合并到一起

2. combineReducers

   function combineReducers(reducers){
     var reducerKeys = Object.keys{reducers}
     var finalReducers = {}
     //将 key对应的对象不是function的reducer过滤掉
     for(var i=0; i < reducerKeys.length; i++){
       var key = reducerKeys[i]

       if(NODE_ENV !== 'production'){
         if(typeof reducers[key] === 'undefined'){
           warning(
             `No reducer provided for key "${key}"`
             )
         }
       }

       if(typeof reducers[key] === 'function'){
         finalReducers[key] = reducers[key]
       }
     }

     //typeof reducer === 'function'
     var finalReducerKeys = Object.keys(finalReducers)

     //combineReducers({})执行后,返回combination方法,执行该方法,返回一个合成state对象,state对象的结构由传入的多个reducer的key决定
     // state对象的结构: {reducerName1: state1, reducerName2: state2}
     return function combination(state = {}, action){
       if (sanityError){
         throw sanityError
       }

       if(NODE_ENV !== 'production'){
         var warningMessage = getUnexpectedStateShapeWarningMessage(state, finalReducers, action, unexpectedKeyCache)
         if (warningMessage){
           warning(warningMessage)
         }
       }

       var hasChanged = false
       var nextState = {}
       for(var i = 0; i < finalReducerKeys.length; i++){
         var key = finalReducerKeys[i]
         var reducer = finalReducers[key]
         var previousStateForKey = state[key]
         var nextStateForKey = reducer(previousStateForKey, action)

         if(typeof nextStateForKey === 'undefined'){
           var errorMessage = getUndefinedStateErrorMessage(key, action)
           throw new Error(errorMessage)
         }

         nextState[key] = nextStateForKey
         hasChanged = hasChanged || nextStateForKey !== previousStateForKey
       }

       return hasChanged ? nextState : state

     }
   }

3. createStore

通过dispatch(action)执行reducer,通过switch判断该执行哪种操作。
通过getState()获取应用当前state

function createStore(reducer, preloadedState, enhancer){
  if(typeof preloadedState === 'function' && typeof enhancer === 'undefined'){
    enhancer = preloadedState
    preloadedState = undefined
  }

  var currentReducer = reducer
  var currentState = preloadedState
  var currentListeners = []
  var nextListeners = currentListeners
  var isDispatching = false

  function getState(){
    return currentState
  }

  function dispatch(action){
    try{
      isDispatching = true
      console.log(`   >>>>>>>>>>>>执行combination start<<<<<<<<<<`);
      currentState = currentReducer(currentState, action)
      console.log(`   >>>>>>>>>>>>执行combination end, 当前state: '${JSON.stringify(currentState)}'  <<<<<<<<<<<<`);
    }finally{
      isDispatching = false
    }

    var listeners = currentListeners = nextListeners
    for(var i=0; i < listeners.length; i++){
      var listener = listeners[i]
      listener()
    }

    return action
  }

  console.log(` >>>>>>>>>>>>>>>>>>>>>初始化state,执行dispatch, start<<<<<<<<<<<<<<<<<<`);
  dispatch({ type: ActionTypes.INIT })
  console.log(` >>>>>>>>>>>>>>>>>>>>>初始化state,执行dispatch, end<<<<<<<<<<<<<<<<<<`);

  return {
    dispatch,
    getState
  }
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值