From 8ec14527dcf0788e0bfb3ebb3f38824ed29e5813 Mon Sep 17 00:00:00 2001 From: Pierre Burgy Date: Wed, 10 May 2017 11:41:53 +0200 Subject: [PATCH] Fix sagas and browserHistory issue --- .../files/admin/public/app/app.js | 1 + .../public/app/app.js | 12 ++++++-- .../public/app/containers/App/selectors.js | 16 +++++++++++ .../public/app/containers/Edit/sagas.js | 17 +++++++---- .../public/app/containers/HomePage/sagas.js | 28 ------------------- .../public/app/containers/List/sagas.js | 12 ++++++-- .../public/app/routes.js | 22 +++++++++------ 7 files changed, 62 insertions(+), 46 deletions(-) delete mode 100644 packages/strapi-plugin-content-manager/public/app/containers/HomePage/sagas.js diff --git a/packages/strapi-generate-admin/files/admin/public/app/app.js b/packages/strapi-generate-admin/files/admin/public/app/app.js index 68ae6c9c25..d1ca42dee9 100644 --- a/packages/strapi-generate-admin/files/admin/public/app/app.js +++ b/packages/strapi-generate-admin/files/admin/public/app/app.js @@ -180,6 +180,7 @@ window.Strapi = { store.dispatch(updatePlugin(pluginId, 'leftMenuLinks', leftMenuLinksUpdated)); }, }), + router: browserHistory, }; const dispatch = store.dispatch; diff --git a/packages/strapi-plugin-content-manager/public/app/app.js b/packages/strapi-plugin-content-manager/public/app/app.js index 9e22ab886f..9257fa18a9 100644 --- a/packages/strapi-plugin-content-manager/public/app/app.js +++ b/packages/strapi-plugin-content-manager/public/app/app.js @@ -6,6 +6,7 @@ */ import { browserHistory } from 'react-router'; +import { syncHistoryWithStore } from 'react-router-redux'; import configureStore from './store'; import React from 'react'; import { Provider } from 'react-redux'; @@ -14,8 +15,15 @@ import { Provider } from 'react-redux'; // this uses the singleton browserHistory provided by react-router // Optionally, this could be changed to leverage a created history // e.g. `const browserHistory = useRouterHistory(createBrowserHistory)();` -const initialState = {}; -const store = configureStore(initialState, browserHistory); +const store = configureStore({}, window.Strapi.router); + +// Sync history and store, as the react-router-redux reducer +// is under the non-default key ("routing"), selectLocationState +// must be provided for resolving how to retrieve the "route" in the state +import { selectLocationState } from 'containers/App/selectors'; +syncHistoryWithStore(window.Strapi.router, store, { + selectLocationState: selectLocationState(), +}); // Set up the router, wrapping all Routes in the App component import App from 'containers/App'; diff --git a/packages/strapi-plugin-content-manager/public/app/containers/App/selectors.js b/packages/strapi-plugin-content-manager/public/app/containers/App/selectors.js index 4764ebd372..c30cc26f02 100644 --- a/packages/strapi-plugin-content-manager/public/app/containers/App/selectors.js +++ b/packages/strapi-plugin-content-manager/public/app/containers/App/selectors.js @@ -9,6 +9,21 @@ const selectGlobalDomain = () => (state) => state.get('global'); * Other specific selectors */ +const selectLocationState = () => { + let prevRoutingState; + let prevRoutingStateJS; + + return (state) => { + const routingState = state.get('route'); // or state.route + + if (!routingState.equals(prevRoutingState)) { + prevRoutingState = routingState; + prevRoutingStateJS = routingState.toJS(); + } + + return prevRoutingStateJS; + }; +}; /** * Default selector used by List @@ -26,6 +41,7 @@ const makeSelectLoading = () => createSelector( export { selectGlobalDomain, + selectLocationState, makeSelectLoading, makeSelectModels, }; diff --git a/packages/strapi-plugin-content-manager/public/app/containers/Edit/sagas.js b/packages/strapi-plugin-content-manager/public/app/containers/Edit/sagas.js index 76a80e86a5..9ed015b6b9 100644 --- a/packages/strapi-plugin-content-manager/public/app/containers/Edit/sagas.js +++ b/packages/strapi-plugin-content-manager/public/app/containers/Edit/sagas.js @@ -1,8 +1,9 @@ import { takeLatest } from 'redux-saga'; -import { put, select, fork, call } from 'redux-saga/effects'; +import { put, select, fork, call, cancel, take } from 'redux-saga/effects'; import request from 'utils/request'; import { browserHistory } from 'react-router'; import { router } from 'app'; +import { LOCATION_CHANGE } from 'react-router-redux'; import { recordLoaded, @@ -46,7 +47,7 @@ export function* editRecord() { const record = yield select(makeSelectRecord()); const recordJSON = record.toJSON(); - const isCreating = yield select(makeSelectIsCreating()); + const isCreating = yield select(makeSelectIsCreating()); const id = isCreating ? '' : recordJSON.id; try { @@ -91,9 +92,15 @@ export function* deleteRecord() { } export function* defaultSaga() { - yield fork(takeLatest, LOAD_RECORD, getRecord); - yield fork(takeLatest, EDIT_RECORD, editRecord); - yield fork(takeLatest, DELETE_RECORD, deleteRecord); + const loadRecordWatcher = yield fork(takeLatest, LOAD_RECORD, getRecord); + const editRecordWatcher = yield fork(takeLatest, EDIT_RECORD, editRecord); + const deleteRecordWatcher = yield fork(takeLatest, DELETE_RECORD, deleteRecord); + + // Suspend execution until location changes + yield take(LOCATION_CHANGE); + yield cancel(loadRecordWatcher); + yield cancel(editRecordWatcher); + yield cancel(deleteRecordWatcher); } // All sagas to be loaded diff --git a/packages/strapi-plugin-content-manager/public/app/containers/HomePage/sagas.js b/packages/strapi-plugin-content-manager/public/app/containers/HomePage/sagas.js deleted file mode 100644 index 6a6809727b..0000000000 --- a/packages/strapi-plugin-content-manager/public/app/containers/HomePage/sagas.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Set of asynchronous functions. - */ - -import { takeLatest } from 'redux-saga'; -import { put, fork } from 'redux-saga/effects'; - -import { - load_success -} from 'containers/HomePage/actions'; - -import { - LOAD -} from 'containers/HomePage/constants'; - - -export function *fetchDefault() { - yield put(load_success({ - name: 'Content Manager' - })); -} - -export function* mySaga() { - yield fork(takeLatest, LOAD, fetchDefault); -} - -// Bootstrap sagas -export default []; diff --git a/packages/strapi-plugin-content-manager/public/app/containers/List/sagas.js b/packages/strapi-plugin-content-manager/public/app/containers/List/sagas.js index 3251b5491e..63b4909b1f 100644 --- a/packages/strapi-plugin-content-manager/public/app/containers/List/sagas.js +++ b/packages/strapi-plugin-content-manager/public/app/containers/List/sagas.js @@ -1,6 +1,7 @@ import { takeLatest } from 'redux-saga'; -import { put, select, fork, call } from 'redux-saga/effects'; +import { put, select, fork, call, take, cancel } from 'redux-saga/effects'; import request from 'utils/request'; +import { LOCATION_CHANGE } from 'react-router-redux'; import { loadedRecord, @@ -71,8 +72,13 @@ export function* getCount() { // Individual exports for testing export function* defaultSaga() { - yield fork(takeLatest, LOAD_RECORDS, getRecords); - yield fork(takeLatest, LOAD_COUNT, getCount); + const loadRecordsWatcher = yield fork(takeLatest, LOAD_RECORDS, getRecords); + const loudCountWatcher = yield fork(takeLatest, LOAD_COUNT, getCount); + + // Suspend execution until location changes + yield take(LOCATION_CHANGE); + yield cancel(loadRecordsWatcher); + yield cancel(loudCountWatcher); } // All sagas to be loaded diff --git a/packages/strapi-plugin-content-manager/public/app/routes.js b/packages/strapi-plugin-content-manager/public/app/routes.js index 83f9f4334a..7d3695f0ce 100644 --- a/packages/strapi-plugin-content-manager/public/app/routes.js +++ b/packages/strapi-plugin-content-manager/public/app/routes.js @@ -26,8 +26,10 @@ export default function createRoutes(store) { const renderRoute = loadModule(cb); - injectReducer('home', reducer.default); - renderRoute(component); + process.nextTick(() => { + kinjectReducer('home', reducer.default); + renderRoute(component); + }); }, }, { path: '/:slug', @@ -39,9 +41,11 @@ export default function createRoutes(store) { const renderRoute = loadModule(cb); - injectReducer('list', reducer.default); - injectSagas(sagas.default); - renderRoute(component); + process.nextTick(() => { + injectReducer('list', reducer.default); + injectSagas(sagas.default); + renderRoute(component); + }); }, }, { path: '/:slug/:id', @@ -53,9 +57,11 @@ export default function createRoutes(store) { const renderRoute = loadModule(cb); - injectReducer('edit', reducer.default); - injectSagas(sagas.default); - renderRoute(component); + process.nextTick(() => { + injectReducer('edit', reducer.default); + injectSagas(sagas.default); + renderRoute(component); + }); }, }, ];