From 449f7a056834dd32b35e7121e13c628825da97eb Mon Sep 17 00:00:00 2001 From: Peter Hudec Date: Mon, 19 Feb 2024 15:31:12 +0000 Subject: [PATCH] Simplified redux setup --- .storybook/preview.js | 4 --- src/client/index.jsx | 9 +------ src/client/middleware.js | 29 --------------------- src/client/provider.jsx | 55 ++++++++++++++++++++++++++++++++-------- 4 files changed, 46 insertions(+), 51 deletions(-) delete mode 100644 src/client/middleware.js diff --git a/.storybook/preview.js b/.storybook/preview.js index c9b993ff830..619b7e28ff1 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -4,7 +4,6 @@ import { createGlobalStyle } from 'styled-components' import '../src/client/components' import DataHubProvider from '../src/client/provider' -import { store, history, sagaMiddleware } from '../src/client/middleware' import taskStoriesTasks from '../src/client/components/Task/__stories__/tasks.js' import typeaheadTasks from '../src/client/components/Typeahead/tasks.js' import contactTasks from '../src/client/components/Resource/__stories__/tasks.js' @@ -25,9 +24,6 @@ export const decorators = [ <> ReactSentry.captureException(error)} > - + {(props) => } diff --git a/src/client/middleware.js b/src/client/middleware.js deleted file mode 100644 index 4e011cc88c3..00000000000 --- a/src/client/middleware.js +++ /dev/null @@ -1,29 +0,0 @@ -import { configureStore } from '@reduxjs/toolkit' -import createSagaMiddleware from 'redux-saga' -import { connectRouter, routerMiddleware } from 'connected-react-router' -import queryString from 'qs' -import { createBrowserHistory } from 'history' - -import { reducers } from './reducers' - -const preloadedState = { - referrerUrl: window.document.referrer, -} - -const sagaMiddleware = createSagaMiddleware() - -const history = createBrowserHistory({ - // The baseURI is set to the tag by the spaFallbackSpread - // middleware, which should be applied to each Express route where - // react-router is expected to be used. - basename: queryString.stringify(new URL(document.baseURI).pathname), -}) - -const store = configureStore({ - devTools: process.env.NODE_ENV === 'development', - middleware: [sagaMiddleware, routerMiddleware(history)], - preloadedState, - reducer: { ...reducers, router: connectRouter(history) }, -}) - -export { store, history, sagaMiddleware } diff --git a/src/client/provider.jsx b/src/client/provider.jsx index 5067ab71283..b78905e574e 100644 --- a/src/client/provider.jsx +++ b/src/client/provider.jsx @@ -1,9 +1,49 @@ import React from 'react' import _ from 'lodash' -import { ConnectedRouter } from 'connected-react-router' +import { + ConnectedRouter, + connectRouter, + routerMiddleware, +} from 'connected-react-router' +import { configureStore } from '@reduxjs/toolkit' import { Provider } from 'react-redux' +import createSagaMiddleware from 'redux-saga' +import { createBrowserHistory } from 'history' import rootSaga from './root-saga' +import { reducers } from './reducers' + +const preloadedState = { + // Extract data provided throught the nunjucks "react-slot" macro + ...JSON.parse(document.getElementById('react-app')?.dataset.props || '{}'), + referrerUrl: window.document.referrer, +} + +const sagaMiddleware = createSagaMiddleware() + +const history = createBrowserHistory({ + // The baseURI is set to the tag by the spaFallbackSpread + // middleware, which should be applied to each Express route where + // react-router is expected to be used. + basename: encodeURIComponent(new URL(document.baseURI).pathname), +}) + +const store = configureStore({ + devTools: process.env.NODE_ENV === 'development', + middleware: [sagaMiddleware, routerMiddleware(history)], + preloadedState, + reducer: { + // This is to prevent the silly "Unexpected key ..." error thrown by combineReducers + ..._.mapValues( + preloadedState, + () => + (state = null) => + state + ), + ...reducers, + router: connectRouter(history), + }, +}) const runMiddlewareOnce = _.once((tasks, sagaMiddleware) => sagaMiddleware.run(rootSaga(tasks)) @@ -13,8 +53,9 @@ const runMiddlewareOnce = _.once((tasks, sagaMiddleware) => * Provides state management and routing infrastructure required by the * stateful/routed components. * @param {Object} props - * @param {Object} props.tasks - A map of _task_ names to _tasks_, if required - * by the wrapped components. + * @param {Collection Promise>} props.tasks - + * A map of _task_ names to _tasks_, if required by the wrapped components. + * @param {React.ReactNode} props.children - Children to which the context will be provided * @example * import ReferralList from 'components/ReferralList' * import dummyReferralListTask from 'components/ReferralList/task/dummy' @@ -25,13 +66,7 @@ const runMiddlewareOnce = _.once((tasks, sagaMiddleware) => * * */ -const DataHubProvider = ({ - tasks, - store, - history, - sagaMiddleware, - children, -}) => { +const DataHubProvider = ({ tasks, children }) => { runMiddlewareOnce(tasks, sagaMiddleware) return (