React-Redux:组合减速器:意外的键

React-Redux: Combining reducers: Unexpected Keys

在我开始组合我的 Redux 减速器之前,我的应用程序运行良好。但是当我组合时,initialState 和 reducer 键混淆了。

function flash(state = [], action) {
  switch (action.type) {
  case FLASH_MESSAGE_UPDATED:
    return _.extend({}, state, { flash: action.flash })
  default:
    return state
  }
}

function events(state = [], action) {
  switch (action.type) {
  case EVENTS_UPDATED:
    return _.extend({}, state, { events: action.pathway_events })
  default:
    return state
  }
}

export default combineReducers({
  events,
  flash
})

这会导致功能损坏和控制台错误

Unexpected keys "one", "two" found in initialState argument passed to createStore. Expected to find one of the known reducer keys instead: "events", "flash". Unexpected keys will be ignored.

我的初始状态是在redux-thunk的帮助下传入的。

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import reducer from '../../reducers/event'

let initialState = {
  one: globalData.one,
  two: globalData.two,
  events: globalData.events,
  flash: globalData.flash
}
let createStoreWithMiddleware = applyMiddleware(thunk)(createStore)
let reduxStore = createStoreWithMiddleware(reducer, initialState);

React.render(
  <Provider store={reduxStore}>
    <EventListContainer />
  </Provider>,
  $('.events')[0]
)

如何正确组合减速器?

我认为您只需要为额外的键添加缩减器,例如

function one(state = {}, action) {
  switch (action.type) {
  case ONE_UPDATED:
    return action.one
  default:
    return state
  }
}

来自the docs

If you produced reducer with combineReducers, this must be a plain object with the same shape as the keys passed to it. Otherwise, you are free to pass anything that your reducer can understand.

如果您不需要处理与 onetwo 相关的任何操作,只需在一开始就将它们拉入,这可以像

一样简单
export default combineReducers({
  events,
  flash,
  one: (state = {}) => state,
  two: (state = {}) => state
})

tl;博士

如果您执行 SSR,请重新编译您的服务器端包!

说明

当您进行服务器端渲染 (SSR) 时,可能会出现此错误消息,更改减速器代码中的某些内容 ,而您 recompile/HMR 在客户端.

当你做 SSR 时,你必须将你的 Redux store 序列化为一个全局变量(比如 window.__INITIAL_STATE__),所以当你初始化客户端时,createStore 可以读取它并构建它Redux 状态。

如果您不为服务器端重新编译修改后的代码,服务器的初始状态可能仍包含具有旧密钥的状态(来自旧的 reducer)而客户端有新状态(来自 new/modified 减速器)。

从技术上讲,这不会破坏客户端的工作方式,因为 Redux 会忽略意外键,它只是一个有用的警告(并不是真正的错误),它会提醒您重新编译服务器端包。不过,这可能是生产中或基准测试 hydration 性能时的一个问题,因为不同的状态会导致不同的 DOM。当然,这个错误不应该发生在生产环境中,因为您的部署过程应该会自动创建客户端和服务器端包。