Использование redux с redux-persist с рендерингом на стороне сервера - PullRequest
0 голосов
/ 06 ноября 2018

Я пытаюсь реализовать redux 4.0.0 с redux-persist 5.10.0 в приложении SSR и столкнулся с проблемой, из-за которой я не могу должным образом предоставить createStore() с предварительно загруженным состоянием без сбоя приложения.

В результате приложение загружается с начальным состоянием с сервера, но когда приложение пытается предварительно загрузить состояние на клиенте в createStore(), оно обновляется и вылетает. Я предполагаю, что это потому, что мой preloadedState не в правильном формате?

Но я не уверен, потому что я не получаю никаких сообщений об ошибках в консоли, пользовательском интерфейсе, нада.

Вот соответствующий код:

магазин / index.js

export default function configureStore(preloadedState = {}) {
    // This will store our enhancers for the store
    const enhancers = [];

    // Add thunk middleware
    const middleware = [thunk];

    // Apply middlware and enhancers
    const composedEnhancers = compose(
        applyMiddleware(...middleware),
        ...enhancers
    );

    // Set up persisted and combined reducers
    const persistedReducer = persistReducer(persistConfig, rootReducer);

    // Create the store with the persisted reducers and middleware/enhancers
    const store = createStore(persistedReducer, preloadedState, composedEnhancers);

    const persistor = persistStore(store, null, () => {
        store.getState(); // if you want to get restoredState
    });

    return { store, persistor };
}

index.js

const preloadedState = window.__PRELOADED_STATE__ ? window.__PRELOADED_STATE__ : {};
delete window.__PRELOADED_STATE__;

// Create redux store
const { persistor, store } = configureStore(preloadedState);

// Get app's root element
const rootEl = document.getElementById("root");

// Determine if we should use hot module rendering or DOM hydration
const renderMethod = !!module.hot ? ReactDOM.render : ReactDOM.hydrate;

renderMethod(
    <Provider store={store}>
        <PersistGate loading={<Loader />} persistor={persistor}>
            <BrowserRouter>
                <App />
            </BrowserRouter>
        </PersistGate>
    </Provider>,
    rootEl
);

Вещи сохраняются и еще много разрабатываются на клиенте, но когда я тестирую SSR, приложение загружается, а затем перезагружается и гаснет. Это перезагрузка заставляет меня думать, что состояние не гидратируется с теми же данными. в этот момент я полностью сбит с толку.

Есть идеи, как поступить ??

EDIT

После некоторой отладки старой школы я обнаружил, что удаление строки <PersistGate loading={<Loader />} persistor={persistor}> позволит приложению изначально загружаться, а вещи загружаются через сервер, как и ожидалось, но данные не сохраняются должным образом (очевидно).

Что-то не так с тем, как я использую компонент PersistGate?

окно .__ PRELOADED_STATE __

{
    user: {…}, banners: {…}, content: {…}, locations: {…}, news: {…}, …}
    banners: {isLoading: 0, banners: Array(2)}
    content: {isLoading: 0, errors: {…}, data: {…}}
    locations: {countries: Array(0), provinces: Array(0), default_country: null, isLoading: false, error: null, …}
    news: {isLoading: 0, hasError: 0}
    phoneTypes: {isLoading: false}
    profileStatuses: {isLoading: false}
    profileTypes: {isLoading: false}
    reviewers: {isLoading: false}
    route: {}
    salutations: {isLoading: false}
    sectors: {isLoading: false, sectors: Array(0)}
    siteInfo: {pageTitle: "", isLoading: 0, hasError: 0, error: "", site: {…}, …}
    sort: {value: "", dir: ""}
    user: {isLoading: false, loginChecked: {…}, admin: null, reviewer: null, loginTokenLoading: false, …}
    _persist: {version: -1, rehydrated: true}
    __proto__: Object
}

1 Ответ

0 голосов
/ 08 июля 2019

Одно из решений, которое у меня сработало, следующее:

  • Определите все действия и редукторы, определенные в магазине, без использования redux-persist. Предоставьте метод createStore, который принимает в качестве аргумента редуктор.
  • На сервере импортируйте редукторы, определенные в хранилище, и создайте хранилище renderToString ().
  • На клиенте импортируйте те же редукторы, создайте постоянный редуктор, используя «хранилище» (обратите внимание, что «хранилище» не работает на сервере, поэтому мы должны импортировать его только на клиенте). Кроме того, создайте хранилище, используя состояние избыточности, отправленное с сервера, и этот постоянный редуктор. Теперь сохраните этот магазин и используйте этот магазин (в провайдере) и персистор (в PersistGate)

Для меня это хорошо работает, если все переменные, которые я пытаюсь сохранить, являются частью компонентов. Другие переменные, которыми вы можете управлять, используя пост звонки на сервер (используя {axios} внутри компонентов).

Проверьте этот репозиторий на предмет создания хранилища без приставки - выполните описанные выше шаги после этого - https://github.com/alexnm/react-ssr/tree/fetch-data

...