注入 asyncReducers 时的 preloadedState
preloadedState when injecting asyncReducers
怎么可能既有预加载状态(从服务器补水)又动态注入减速器?
在 react-boilerplate
或 中有减速器的概念,它是根据您正在查看的 page/components 动态添加的。摘自reducers.js
:
export default function createReducer(asyncReducers) {
return combineReducers({
users,
posts,
...asyncReducers
});
}
虽然这在从一个页面导航到另一个页面(或仅客户端应用程序)时效果很好;从服务器合并数据时遇到此错误:
Unexpected property "comments" found in previous state received by the reducer. Expected to find one of the known reducer property names instead: "users", "posts". Unexpected properties will be ignored.
(其中comments
是动态注入reducer的属性名称)
这个错误的原因很明显,因为来自服务器(使用 React SSR)的 preloadedState
已经包含 comments
而初始 reducer 没有,因为这是后来动态添加的。如果我将 comments
添加到我的 combineReducers
中,错误就会消失;然而,这意味着在应用程序初始化时,我需要包括所有减速器;这并不理想。
您应该能够使用虚拟 reducer 代替动态加载的 reducer,动态加载的 reducer 将在加载真正的 reducer 时被替换。
{ comments: (state = null) => state }
这也可以自动完成,具体取决于您的实施,根据 http://nicolasgallagher.com/redux-modules-and-code-splitting/
// Preserve initial state for not-yet-loaded reducers
const combine = (reducers) => {
const reducerNames = Object.keys(reducers);
Object.keys(initialState).forEach(item => {
if (reducerNames.indexOf(item) === -1) {
reducers[item] = (state = null) => state;
}
});
return combineReducers(reducers);
};
怎么可能既有预加载状态(从服务器补水)又动态注入减速器?
在 react-boilerplate
或 reducers.js
:
export default function createReducer(asyncReducers) {
return combineReducers({
users,
posts,
...asyncReducers
});
}
虽然这在从一个页面导航到另一个页面(或仅客户端应用程序)时效果很好;从服务器合并数据时遇到此错误:
Unexpected property "comments" found in previous state received by the reducer. Expected to find one of the known reducer property names instead: "users", "posts". Unexpected properties will be ignored.
(其中comments
是动态注入reducer的属性名称)
这个错误的原因很明显,因为来自服务器(使用 React SSR)的 preloadedState
已经包含 comments
而初始 reducer 没有,因为这是后来动态添加的。如果我将 comments
添加到我的 combineReducers
中,错误就会消失;然而,这意味着在应用程序初始化时,我需要包括所有减速器;这并不理想。
您应该能够使用虚拟 reducer 代替动态加载的 reducer,动态加载的 reducer 将在加载真正的 reducer 时被替换。
{ comments: (state = null) => state }
这也可以自动完成,具体取决于您的实施,根据 http://nicolasgallagher.com/redux-modules-and-code-splitting/
// Preserve initial state for not-yet-loaded reducers
const combine = (reducers) => {
const reducerNames = Object.keys(reducers);
Object.keys(initialState).forEach(item => {
if (reducerNames.indexOf(item) === -1) {
reducers[item] = (state = null) => state;
}
});
return combineReducers(reducers);
};