将initialState中的数据与来自服务器

时间:2017-12-16 16:00:52

标签: javascript redux

我有一个这样的状态形状(在postReducer上设置为initialState):

{
  posts: {
    isFetching: false,
    hasFetched: false,
    items: []
  }
}

我想通过在HTML中嵌入JSON(不覆盖itemsisFetching)来设置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)
);

2 个答案:

答案 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__,
}