redux入门 互动版

combineReducers的使用

本小节我们将自己实现一个我们程序可以用的combineReducers函数,并带大家看一看Redux是怎么样实现combineReducers函数的。

1、简单combineReducers函数的实现

在写combineReducers之前我们先来了解一下combineReducers是用来干嘛的。

大家知道我们的reducer最终返回的是一个完整的state,combineReducers起的作用就是将每个子reducer拼接起来返回一个完整的state,那么写出一个简单的combineReducers就不难了。

看下面的例子:

function todoApp(state = initState,action){
  return {
      filter:setFilter(state.filter,action),
        todos:todos(state.todos,action)
    };
}

2、源码中的combineReducers

想必大家也和我一样想知道源码中的combineReducers又是怎么实现的呢?

原理大家都知道了,就是用来拼接,知道了原理看懂源码也就不难了,下面带大家过一遍下面贴出来的部分源码。

A、首先我们可以看到它用reducerKeys、finalReducers分别记录了键值和子reducer函数

B、返回了一个函数,当然这个函数就是我们的根reducer。下面再看看这个reducer做了什么

C、先通过arguments将state获取,你们可以看到,他也对state做了处理,在这里提醒一下,像我们在源码里看到的一样,大家在写reducer的时候在default一定要返回一个默认的state

D、再看我们就能看到一个循环,大家都明白,就是用来执行保存在finalReducers中的reducer函数的,用nextState记录获取到state,然后比较获取到的state和是否改变

E、如果改变就返回新的state

希望大家看完之后除了更了解combineReducers之外,还要记住设计reducer的一些原则。

function combineReducers(reducers) {
    //获取每个子reducer函数,以及对应的键值
    var reducerKeys = Object.keys(reducers);
    var finalReducers = {};
    for (var i = 0; i < reducerKeys.length; i++) {
      var key = reducerKeys[i];
      if (typeof reducers[key] === 'function') {
        finalReducers[key] = reducers[key];
      }
    }
    var finalReducerKeys = Object.keys(finalReducers);
    //......

    return function combination() {
      var state = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
        var action =  arguments[1];
      //......

      //执行每个子reducer函数,如果state发生变化,则返回新的state
      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);
        //......
        nextState[key] = nextStateForKey;
        hasChanged = hasChanged || nextStateForKey !== previousStateForKey;
      }
      return hasChanged ? nextState : state;
    };
}

3、使用combineReducers

当然我们也可以自行实现不同功能的combineReducers,也可以直接明确的写一个根reducer,但是在此我们使用redux提供的combineReducers。

var todoApp = combineReducers({
  filter:setFilter,
    todos:todos
});
在右方代码区练习使用combineReducers