不止前端
首发于不止前端

关于combineReducers两个有趣的问题

抛两个问题

  1. 如果两个reducer含有处理相同action的代码,combine后会怎样?
  2. 如果一个对象同时被两个reducer作为初始state,然后含有处理相同action的代码,又会怎样?

还是做一下试验吧

const reducer1 = function(state = 0, action){
    switch(action.type) {
        case "ADD":
            state = state + 1
    }
    return state;
}

const reducer2 = function(state = 0, action) {
    switch(action.type) {
        case "ADD":
            state = state + 1
    }
    return state;
}

const reducer = combineReducers({
    A: reducer1,
    B: reducer2
})
console.log(reducer)

const store = createStore(reducer)

console.log(store);

console.log(store.getState())

这段初始化的代码执行完成后,看一下console的输出

没啥意外的,然后我定义一个组件,加一个事件用来触发store.dispatch

export default class ReducerTest extends Component{
    add = () => {
        store.dispatch({
            type: "ADD"
        });
        console.log(store.getState())
    }
    render() {
        return <button onClick={this.add}>Add </button>
    }
}

点了三下按钮

第一个问题得到了解答,尚在正常的思路内

现在改一下代码

const initState = {
    value: 0
}

const reducer1 = function(state = initState, action){
    switch(action.type) {
        case "ADD":
            console.log("reducer1中被触发")
            state = {
                value: state.value + 1
            }
    }
    return state;
}

const reducer2 = function(state = initState, action) {
    switch(action.type) {
        case "ADD":
        console.log("reducer2中被触发")
        state = {
            value: state.value + 1
        }
    }
    return state;
}

const reducer = combineReducers({
    A: reducer1,
    B: reducer2
})
console.log(reducer)

const store = createStore(reducer)

console.log(store)

console.log(store.getState().A === store.getState().B)


export default class ReducerTest extends Component{
    add = () => {
        store.dispatch({
            type: "ADD"
        });
        console.log(store.getState())
    }

    render() {
        return <button onClick={this.add}>Add </button>
    }

}

点击按钮后看一下输出

有点奇怪,A和B是同一个对象,然后A和B中的reducer都被触发,但是值只增加了1。

还是要从源码上找出答案来

看两个红圈的地方,在这个方法里循环调用reducer。注意state变量,是从方法的参数中传递过来的,意味着在第一个reducer执行完后的变化还没有对这个state产生影响,在第二个reducer执行的时候还是原来state的值。

从性能角度考虑,state的变化也应该是一次性调整,而不是每次变化后就触发,跟React的setState一样。

发布于 2018-06-04

文章被以下专栏收录