通过代码拆分和注入来实现Redux Server Side Rendering

时间:2019-10-31 10:46:51

标签: reactjs redux redux-saga

对不起,英语不好。

我在用ssr(pure react)+ redux +代码拆分(@loadable)+注入redux挣扎。 (受反应样板的影响很大)

当前,我的代码在没有预加载数据的情况下运行良好。

我不知道在注入reducer之前如何处理ssr预加载数据。

下面是帮助解决我的问题的示例。

store = {
  global: { // default
    key: 'value' // this is done. ssr working great using this value.
  },
  injected: { // dynamically injected. using replaceReducer per page. (same with react-boilerplate)
    key: 'value' // I want to put this value on ssr preload. (not working)
  }
}

说完了

Unexpected property "injected" found in previous state received by the reducer. Expected to find one of the known reducer property names instead: "global". Unexpected properties will be ignored.

我知道为什么会出现此错误(因为初始存储没有“已注入”存储。),但我不知道如何正确修复它。

有没有用法示例?

这是我的想法,但这似乎不是正确的答案。

  1. 在“全局”上插入用于预加载数据的键。
  2. 将预加载数据放在服务器中的“全局”上。
  3. 完成注入后,将全局移动到注入的商店(在本例中为“ injected”)。
  4. 瞧!

1 个答案:

答案 0 :(得分:0)

reducerInjector.js

export const injectState = (reducers, preloadedState = {}) =>
  Object.keys(reducers).reduce((result, key) => {
    const finalReducers = result;
    if (typeof reducers[key] === 'function') {
      finalReducers[key] = (state = preloadedState[key], action) => reducers[key](state, action);
    }
    return finalReducers;
  }, {});

export const createInitialState = (reducers, preloadedState = {}) =>
  Object.keys(preloadedState).reduce((r, key) => {
    if (!reducers[key]) return r;
    return { ...r, [key]: preloadedState[key] };
  }, {});

export const createReducer = (staticReducers, asyncReducers, preloadedState) =>
  combineReducers(injectState({
    ...staticReducers,
    ...asyncReducers,
  }, preloadedState));


export default function reducerInjector(store, staticReducers, preloadedState) {
  // Add a dictionary to keep track of the registered async reducers
  store.asyncReducers = {};

  // Create an inject reducer function
  // This function adds the async reducer, and creates a new combined reducer
  store.injectReducer = (key, asyncReducer) => {
    store.asyncReducers[key] = asyncReducer;
    store.replaceReducer(createReducer(staticReducers, store.asyncReducers, preloadedState));
  };
  return store;
}
...
import reducerInjector, { createReducer, createInitialState } from './reducerInjector';

const configureStore = (initialState, ssr) => {
  const sagaMiddleware = createSagaMiddleware({});
  const createStoreWithMiddleware = compose(applyMiddleware(thunkMiddleware, sagaMiddleware));
  const reducer = createReducer(rootReducer, {}, initialState);
  const initialData = createInitialState(rootReducer, initialState);
  let store = createStoreWithMiddleware(createStore)(reducer, initialData);
  store = reducerInjector(store, rootReducer, initialState);
  return store;
}