我有一个这样的状态形状(在postReducer上设置为initialState):
{
posts: {
isFetching: false,
hasFetched: false,
items: []
}
}
我想通过在HTML中嵌入JSON(不覆盖items
和isFetching
)来设置hasFetched
数组,并在初始渲染时预加载数据:
<script>
window.__PRELOADED_STATE__ = ${JSON.stringify(array_with_posts)}
</script
Redux文档指南recommends处理预加载的数据,如下所示:
const preloadedState = window.__PRELOADED_STATE__
delete window.__PRELOADED_STATE__
const store = createStore(
rootReducer, preloadedState,
composeWithDevTools(middleware)
);
但那只会用items
数组覆盖我的整个状态。
在运行应用程序时设置状态,Redux数据流对我来说是可以理解的,并且只设置一部分状态可以正常工作。但是,如何在启动Redux时仅使用预加载的数据设置状态的一部分?
更新
对于上下文,目前我在创建商店时使用combineReducers()
:
import posts from './reducers/posts'
import comments from './reducers/comments'
const rootReducer = combineReducers({
posts,
comments
});
const store = createStore(
rootReducer,
composeWithDevTools(middleware)
);
答案 0 :(得分:2)
考虑到您的预加载状态是您所说的数组,您可以合并结果并将其用作初始存储。
非Babel解决方案(无扩散对象)
const preloadedState = window.__PRELOADED_STATE__
delete window.__PRELOADED_STATE__
const preMerge = Object.assign({}, counterApp.posts, { items: preloadedState });
const merge = { posts: preMerge };
const store = createStore(merge);
Babel解决方案(带有传播对象)
const preloadedState = window.__PRELOADED_STATE__
delete window.__PRELOADED_STATE__
const merge = {
posts: {
...counterApp.posts,
items: preloadedState,
},
};
const store = createStore(merge);
此外,您可以使用_lodash之类的实用程序来执行深层对象合并(检查_lodash.merge方法)。
更新了上下文:
您必须使用我之前解释过的任何方式将预加载状态合并到rootReducer中。例如,如果使用Babel并且具有使用传播对象的可能性,则可以执行以下操作:
import posts from './reducers/posts'
import comments from './reducers/comments'
const rootReducer = combineReducers({
posts,
comments
});
const preloadedState = window.__PRELOADED_STATE__
delete window.__PRELOADED_STATE__
const preloadStateMergedIntoRootReducer = {
...rootReducer,
posts: {
...rootReducer.posts,
items: preloadedState,
},
};
const store = createStore(
preloadStateMergedIntoRootReducer,
composeWithDevTools(middleware)
);
正如我之前所说,你还有其他选择。如果你不想要计算你需要传播的rootReducer对象的哪个属性并进行深度合并,那么你可以使用前面提到的_lodash或例如Inmutable.js这样的库来为你做法。
答案 1 :(得分:1)
一种解决方案是创建具有所需形状的preloadedState
:
const preloadedState = {
isFetching: false,
hasFetched: false,
items: window.__PRELOADED_LOADED_STATE__,
}