redux中不同reducer相互影响?

有两个不同的reducer

const initialArticlesState = {
  list: [],
  isFetching: false,
  pageIndex: 1,
  pageNum: 10
}

const initialStickyArticlesState = {
  list: [],
  isShowLogo: true,
  isFetching: false,
}

function articlesReducer(state = initialArticlesState, action) {
  switch (action.type) {
    case GET_ARTICLES_REQUEST:
      return { ...state, isFetching: true }
    case GET_ARTICLES_SUCCESS:
      return {
        ...state,
        list: state.list.concat(action.payload),
        isFetching: false
      }
    case GET_ARTICLES_FAILED:
      return { ...state, isFetching: false }
    default:
      return { ...state, isFetching: false }
  }
}

function stickyArticlesReducer(state = initialStickyArticlesState, action) {
  switch (action.type) {
    case GET_STICKY_ARTICLES_REQUEST:
      return { ...state, isFetching: true }
    case GET_STICKY_ARTICLES_SUCCESS:
      if (action.payload.length > 0) {
        return {
          ...state,
          list: state.list.slice(0, 1).concat(action.payload),
          isFetching: false,
          isShowLogo: false
        }
      } else {
        return { ...state, isFetching: false }
      }
    case GET_STICKY_ARTICLES_FAILED:
      return { ...state, isFetching: false }
    default:
      return { ...state, isFetching: false }
  }
}

先执dispatch({type:'GET_ARTICLES_REQUEST'}),然后执行dispatch({type: 'GET_STICKY_ARTICLES_REQUEST'}),基本就是上下行的关系

执行dispatch({type:'GET_ARTICLES_REQUEST'})的时候aticles.isFetching=true,这是对的;然后执行dispatch({type: 'GET_STICKY_ARTICLES_REQUEST'})的时候,aticles.isFetching=false了,这里怎么将另一个reducer的isFetching变成了false了啊?????

上图:
图片描述
图片描述

阅读 4.3k
3 个回答

作者:pawn
链接:https://www.zhihu.com/questio...
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

在redux 内部,有一个 combineReducers 函数,它会组合所有的子 reducer ,并返回最终的 reducer 。附上combineReducers 精简版的源代码function combineReducers(reducers) {

// 这儿返回的函数就是最终的reducer 
return function (state, action) {
    const keys = Object.keys(reducers)

    const newState = {}
    keys.forEach(key => {
        newState[key] = reducers[key](state[key], action)
    })
    return newState
}

}
可以看到, 对于每一个 dispatch, redux 内部都会走所有的子 reducer 的。在题主的代码中, default:

return { ...state, isFetching: false }

}
这句就会导致,不管发出什么dispatch, articles 的 isFetching 都会被置为false 。建议这里不要在 default: 中更改state,只返回state就好 。 reducer default 有2个用处初始化state , 在redux 内部, 会执行 state = dispatch({}) 来初始化state 。在combineReducers 后, 防止其它reducer 的dispatch 相互干扰 。以上 。

我来精简一下,每次dispatch,所有的子Reducer都会执行一次, 子Reducer中action.type相同则执行相应的数据处理并且返回,如果整个子Reducer都没有匹配到当前action.type,那么会执行default下逻辑处理.
再说到这里, default应该只返回当前最新的状态集合,这样才会保证页面绑定的此部分状态不变.如果default中做了数据状态处理,那么数据的状态必然是会改变的.
再举个列子:
A_action 触发 => A_reducer处理,此时B_reducer也会因为A_action的触发而执行,只是没有匹配到自己能处理action.type,所以B_reducer最后执行了default下的逻辑.

新手上路,请多包涵

每次dispatch,所有的子reducer都会去执行一次

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏