diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index bd03a5ad0ee5e..1e5a73b39343b 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -20,6 +20,7 @@ "@emotion/react": "^11.4.1", "@emotion/styled": "^11.3.0", "@fontsource/inter": "^4.0.0", + "@reduxjs/toolkit": "^1.9.3", "@superset-ui/chart-controls": "file:./packages/superset-ui-chart-controls", "@superset-ui/core": "file:./packages/superset-ui-core", "@superset-ui/legacy-plugin-chart-calendar": "file:./plugins/legacy-plugin-chart-calendar", @@ -133,7 +134,7 @@ "react-virtualized": "9.19.1", "react-virtualized-auto-sizer": "^1.0.7", "react-window": "^1.8.8", - "redux": "^4.0.5", + "redux": "^4.2.1", "redux-localstorage": "^0.4.1", "redux-thunk": "^2.1.0", "redux-undo": "^1.0.0-beta9-9-7", @@ -13781,6 +13782,29 @@ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/@reduxjs/toolkit": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.3.tgz", + "integrity": "sha512-GU2TNBQVofL09VGmuSioNPQIu6Ml0YLf4EJhgj0AvBadRlCGzUWet8372LjvO4fqKZF2vH1xU0htAa7BrK9pZg==", + "dependencies": { + "immer": "^9.0.16", + "redux": "^4.2.0", + "redux-thunk": "^2.4.2", + "reselect": "^4.1.7" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18", + "react-redux": "^7.2.1 || ^8.0.2" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, "node_modules/@samverschueren/stream-to-observable": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz", @@ -36711,9 +36735,9 @@ } }, "node_modules/immer": { - "version": "9.0.6", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.6.tgz", - "integrity": "sha512-G95ivKpy+EvVAnAab4fVa4YGYn24J1SpEktnJX7JJ45Bd7xqME/SCplFzYFmTbrkwZbQ4xJK1xMTUYBkN6pWsQ==", + "version": "9.0.19", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.19.tgz", + "integrity": "sha512-eY+Y0qcsB4TZKwgQzLaE/lqYMlKhv5J9dyd2RhhtGhNo2njPXDqU9XPfcNfa3MIDsdtZt5KlkIsirlo4dHsWdQ==", "funding": { "type": "opencollective", "url": "https://opencollective.com/immer" @@ -51351,12 +51375,11 @@ } }, "node_modules/redux": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz", - "integrity": "sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", "dependencies": { - "loose-envify": "^1.4.0", - "symbol-observable": "^1.2.0" + "@babel/runtime": "^7.9.2" } }, "node_modules/redux-localstorage": { @@ -51374,9 +51397,12 @@ } }, "node_modules/redux-thunk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz", - "integrity": "sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw==" + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", + "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==", + "peerDependencies": { + "redux": "^4" + } }, "node_modules/redux-undo": { "version": "1.0.0-beta9-9-7", @@ -52589,9 +52615,9 @@ "devOptional": true }, "node_modules/reselect": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.0.0.tgz", - "integrity": "sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA==" + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.7.tgz", + "integrity": "sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A==" }, "node_modules/resize-observer-polyfill": { "version": "1.5.1", @@ -72550,6 +72576,17 @@ "@react-spring/types": "~9.6.1" } }, + "@reduxjs/toolkit": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.3.tgz", + "integrity": "sha512-GU2TNBQVofL09VGmuSioNPQIu6Ml0YLf4EJhgj0AvBadRlCGzUWet8372LjvO4fqKZF2vH1xU0htAa7BrK9pZg==", + "requires": { + "immer": "^9.0.16", + "redux": "^4.2.0", + "redux-thunk": "^2.4.2", + "reselect": "^4.1.7" + } + }, "@samverschueren/stream-to-observable": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz", @@ -91076,9 +91113,9 @@ "optional": true }, "immer": { - "version": "9.0.6", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.6.tgz", - "integrity": "sha512-G95ivKpy+EvVAnAab4fVa4YGYn24J1SpEktnJX7JJ45Bd7xqME/SCplFzYFmTbrkwZbQ4xJK1xMTUYBkN6pWsQ==" + "version": "9.0.19", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.19.tgz", + "integrity": "sha512-eY+Y0qcsB4TZKwgQzLaE/lqYMlKhv5J9dyd2RhhtGhNo2njPXDqU9XPfcNfa3MIDsdtZt5KlkIsirlo4dHsWdQ==" }, "immutable": { "version": "3.8.2", @@ -102276,12 +102313,11 @@ } }, "redux": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz", - "integrity": "sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", "requires": { - "loose-envify": "^1.4.0", - "symbol-observable": "^1.2.0" + "@babel/runtime": "^7.9.2" } }, "redux-localstorage": { @@ -102299,9 +102335,10 @@ } }, "redux-thunk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz", - "integrity": "sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw==" + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", + "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==", + "requires": {} }, "redux-undo": { "version": "1.0.0-beta9-9-7", @@ -103186,9 +103223,9 @@ "devOptional": true }, "reselect": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.0.0.tgz", - "integrity": "sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA==" + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.7.tgz", + "integrity": "sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A==" }, "resize-observer-polyfill": { "version": "1.5.1", diff --git a/superset-frontend/package.json b/superset-frontend/package.json index 1ebf6842e0c08..f9dce7757d51c 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -84,6 +84,7 @@ "@emotion/react": "^11.4.1", "@emotion/styled": "^11.3.0", "@fontsource/inter": "^4.0.0", + "@reduxjs/toolkit": "^1.9.3", "@superset-ui/chart-controls": "file:./packages/superset-ui-chart-controls", "@superset-ui/core": "file:./packages/superset-ui-core", "@superset-ui/legacy-plugin-chart-calendar": "file:./plugins/legacy-plugin-chart-calendar", @@ -197,7 +198,7 @@ "react-virtualized": "9.19.1", "react-virtualized-auto-sizer": "^1.0.7", "react-window": "^1.8.8", - "redux": "^4.0.5", + "redux": "^4.2.1", "redux-localstorage": "^0.4.1", "redux-thunk": "^2.1.0", "redux-undo": "^1.0.0-beta9-9-7", diff --git a/superset-frontend/packages/superset-ui-core/src/chart/components/SuperChart.tsx b/superset-frontend/packages/superset-ui-core/src/chart/components/SuperChart.tsx index 098fd483656fd..f6742eedd9505 100644 --- a/superset-frontend/packages/superset-ui-core/src/chart/components/SuperChart.tsx +++ b/superset-frontend/packages/superset-ui-core/src/chart/components/SuperChart.tsx @@ -103,8 +103,10 @@ class SuperChart extends React.PureComponent { private createChartProps = ChartProps.createSelector(); private parseDimension = createSelector( - ({ width }: { width: string | number; height: string | number }) => width, - ({ height }) => height, + [ + ({ width }: { width: string | number; height: string | number }) => width, + ({ height }) => height, + ], (width, height) => { // Parse them in case they are % or 'auto' const widthInfo = parseLength(width); diff --git a/superset-frontend/packages/superset-ui-core/src/chart/components/SuperChartCore.tsx b/superset-frontend/packages/superset-ui-core/src/chart/components/SuperChartCore.tsx index d818890aa552a..1cec9d68f4f2e 100644 --- a/superset-frontend/packages/superset-ui-core/src/chart/components/SuperChartCore.tsx +++ b/superset-frontend/packages/superset-ui-core/src/chart/components/SuperChartCore.tsx @@ -95,15 +95,17 @@ export default class SuperChartCore extends React.PureComponent { * is changed. */ processChartProps = createSelector( - (input: { - chartProps: ChartProps; - preTransformProps?: PreTransformProps; - transformProps?: TransformProps; - postTransformProps?: PostTransformProps; - }) => input.chartProps, - input => input.preTransformProps, - input => input.transformProps, - input => input.postTransformProps, + [ + (input: { + chartProps: ChartProps; + preTransformProps?: PreTransformProps; + transformProps?: TransformProps; + postTransformProps?: PostTransformProps; + }) => input.chartProps, + input => input.preTransformProps, + input => input.transformProps, + input => input.postTransformProps, + ], (chartProps, pre = IDENTITY, transform = IDENTITY, post = IDENTITY) => post(transform(pre(chartProps))), ); @@ -117,9 +119,11 @@ export default class SuperChartCore extends React.PureComponent { * is changed. */ private createLoadableRenderer = createSelector( - (input: { chartType: string; overrideTransformProps?: TransformProps }) => - input.chartType, - input => input.overrideTransformProps, + [ + (input: { chartType: string; overrideTransformProps?: TransformProps }) => + input.chartType, + input => input.overrideTransformProps, + ], (chartType, overrideTransformProps) => { if (chartType) { const Renderer = createLoadableRenderer({ diff --git a/superset-frontend/plugins/preset-chart-xy/src/components/Line/Line.tsx b/superset-frontend/plugins/preset-chart-xy/src/components/Line/Line.tsx index 6449204ec48fc..465fae408c4fe 100644 --- a/superset-frontend/plugins/preset-chart-xy/src/components/Line/Line.tsx +++ b/superset-frontend/plugins/preset-chart-xy/src/components/Line/Line.tsx @@ -106,11 +106,15 @@ export interface SeriesValue { const CIRCLE_STYLE = { strokeWidth: 1.5 }; export default class LineChart extends PureComponent { - private createEncoder = lineEncoderFactory.createSelector(); + private createEncoder = lineEncoderFactory.createSelector() as ( + encoding: Partial, + ) => LineEncoder; private createAllSeries = createSelector( - (input: { encoder: LineEncoder; data: Dataset }) => input.encoder, - input => input.data, + [ + (input: { encoder: LineEncoder; data: Dataset }) => input.encoder, + input => input.data, + ], (encoder, data) => { const { channels } = encoder; const fieldNames = encoder.getGroupBys(); diff --git a/superset-frontend/plugins/preset-chart-xy/src/utils/createMarginSelector.tsx b/superset-frontend/plugins/preset-chart-xy/src/utils/createMarginSelector.tsx index 759b27ec55f10..37a56140f9b56 100644 --- a/superset-frontend/plugins/preset-chart-xy/src/utils/createMarginSelector.tsx +++ b/superset-frontend/plugins/preset-chart-xy/src/utils/createMarginSelector.tsx @@ -26,10 +26,12 @@ export default function createMarginSelector( defaultMargin: Margin = DEFAULT_MARGIN, ) { return createSelector( - (margin: Partial) => margin.bottom, - margin => margin.left, - margin => margin.right, - margin => margin.top, + [ + (margin: Partial) => margin.bottom, + margin => margin.left, + margin => margin.right, + margin => margin.top, + ], ( bottom = defaultMargin.bottom, left = defaultMargin.left, diff --git a/superset-frontend/spec/fixtures/mockStore.js b/superset-frontend/spec/fixtures/mockStore.js index 119e19a0847d5..3106163a98d09 100644 --- a/superset-frontend/spec/fixtures/mockStore.js +++ b/superset-frontend/spec/fixtures/mockStore.js @@ -16,10 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { createStore, applyMiddleware, compose } from 'redux'; -import thunk from 'redux-thunk'; - -import { rootReducer } from 'src/views/store'; +import { setupStore } from 'src/views/store'; import { FilterBarOrientation } from 'src/dashboard/types'; import mockState from './mockState'; @@ -32,38 +29,38 @@ import { dashboardFilters } from './mockDashboardFilters'; import { nativeFilters, dataMaskWith2Filters } from './mockNativeFilters'; export const storeWithState = state => - createStore(rootReducer, state, compose(applyMiddleware(thunk))); + setupStore({ + disableDebugger: true, + initialState: state, + }); export const getMockStore = overrideState => - createStore( - rootReducer, - { ...mockState, ...overrideState }, - compose(applyMiddleware(thunk)), - ); + setupStore({ + disableDebugger: true, + initialState: { ...mockState, ...overrideState }, + }); export const mockStore = getMockStore(); export const getMockStoreWithTabs = () => - createStore( - rootReducer, - { + setupStore({ + disableDebugger: true, + initialState: { ...mockState, dashboardLayout: dashboardLayoutWithTabs, dashboardFilters: {}, }, - compose(applyMiddleware(thunk)), - ); + }); export const getMockStoreWithChartsInTabsAndRoot = () => - createStore( - rootReducer, - { + setupStore({ + disableDebugger: true, + initialState: { ...mockState, dashboardLayout: dashboardLayoutWithChartsInTabsAndRoot, dashboardFilters: {}, }, - compose(applyMiddleware(thunk)), - ); + }); export const mockStoreWithTabs = getMockStoreWithTabs(); export const mockStoreWithChartsInTabsAndRoot = @@ -101,7 +98,10 @@ export const stateWithFilters = { // one chart with a filter that has been rejected, // and one chart with no filters set. export const getMockStoreWithFilters = () => - createStore(rootReducer, stateWithFilters); + setupStore({ + disableDebugger: true, + initialState: stateWithFilters, + }); export const stateWithNativeFilters = { ...mockState, @@ -132,7 +132,10 @@ export const stateWithNativeFilters = { }; export const getMockStoreWithNativeFilters = () => - createStore(rootReducer, stateWithNativeFilters); + setupStore({ + disableDebugger: true, + initialState: stateWithNativeFilters, + }); export const stateWithoutNativeFilters = { ...mockState, diff --git a/superset-frontend/spec/helpers/testing-library.tsx b/superset-frontend/spec/helpers/testing-library.tsx index 25b0324fe1864..4790b4b718ab2 100644 --- a/superset-frontend/spec/helpers/testing-library.tsx +++ b/superset-frontend/spec/helpers/testing-library.tsx @@ -22,19 +22,12 @@ import { render, RenderOptions } from '@testing-library/react'; import { ThemeProvider, supersetTheme } from '@superset-ui/core'; import { BrowserRouter } from 'react-router-dom'; import { Provider } from 'react-redux'; -import { - combineReducers, - createStore, - applyMiddleware, - compose, - Store, -} from 'redux'; -import thunk from 'redux-thunk'; import { DndProvider } from 'react-dnd'; import { HTML5Backend } from 'react-dnd-html5-backend'; import reducerIndex from 'spec/helpers/reducerIndex'; import { QueryParamProvider } from 'use-query-params'; import QueryProvider from 'src/views/QueryProvider'; +import { configureStore, Store } from '@reduxjs/toolkit'; type Options = Omit & { useRedux?: boolean; @@ -71,11 +64,11 @@ export function createWrapper(options?: Options) { if (useRedux) { const mockStore = store ?? - createStore( - combineReducers(reducers || reducerIndex), - initialState || {}, - compose(applyMiddleware(thunk)), - ); + configureStore({ + preloadedState: initialState || {}, + devTools: false, + reducer: reducers || reducerIndex, + }); result = {result}; } diff --git a/superset-frontend/src/SqlLab/App.jsx b/superset-frontend/src/SqlLab/App.jsx index a86228c6845b0..86b981ae76dfc 100644 --- a/superset-frontend/src/SqlLab/App.jsx +++ b/superset-frontend/src/SqlLab/App.jsx @@ -17,20 +17,18 @@ * under the License. */ import React from 'react'; -import { createStore, compose, applyMiddleware } from 'redux'; +import persistState from 'redux-localstorage'; import { Provider } from 'react-redux'; -import thunkMiddleware from 'redux-thunk'; import { hot } from 'react-hot-loader/root'; import { FeatureFlag, ThemeProvider } from '@superset-ui/core'; import { GlobalStyles } from 'src/GlobalStyles'; import QueryProvider from 'src/views/QueryProvider'; import { initFeatureFlags, isFeatureEnabled } from 'src/featureFlags'; +import { setupStore } from 'src/views/store'; import setupExtensions from 'src/setup/setupExtensions'; import getBootstrapData from 'src/utils/getBootstrapData'; -import logger from 'src/middleware/loggerMiddleware'; import getInitialState from './reducers/getInitialState'; -import rootReducer from './reducers/index'; -import { initEnhancer } from '../reduxUtils'; +import { reducers } from './reducers/index'; import App from './components/App'; import { emptyQueryResults, @@ -109,17 +107,18 @@ const sqlLabPersistStateConfig = { }, }; -const store = createStore( - rootReducer, +export const store = setupStore({ initialState, - compose( - applyMiddleware(thunkMiddleware, logger), - initEnhancer( - !isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE), - sqlLabPersistStateConfig, - ), - ), -); + rootReducers: reducers, + ...(!isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE) && { + enhancers: [ + persistState( + sqlLabPersistStateConfig.paths, + sqlLabPersistStateConfig.config, + ), + ], + }), +}); // Highlight the navbar menu const menus = document.querySelectorAll('.nav.navbar-nav li.dropdown'); diff --git a/superset-frontend/src/SqlLab/reducers/index.js b/superset-frontend/src/SqlLab/reducers/index.js index 8ae0608ef6154..35c16ba2e1953 100644 --- a/superset-frontend/src/SqlLab/reducers/index.js +++ b/superset-frontend/src/SqlLab/reducers/index.js @@ -22,9 +22,11 @@ import sqlLab from './sqlLab'; import localStorageUsageInKilobytes from './localStorageUsage'; import common from './common'; -export default combineReducers({ +export const reducers = { sqlLab, localStorageUsageInKilobytes, messageToasts, common, -}); +}; + +export default combineReducers(reducers); diff --git a/superset-frontend/src/views/menu.tsx b/superset-frontend/src/views/menu.tsx index fed5782a5643c..6c06ab2ff469a 100644 --- a/superset-frontend/src/views/menu.tsx +++ b/superset-frontend/src/views/menu.tsx @@ -34,7 +34,7 @@ import { setupStore } from './store'; // Disable connecting to redux debugger so that the React app injected // Below the menu like SqlLab or Explore can connect its redux store to the debugger -const store = setupStore(true); +const store = setupStore({ disableDebugger: true }); const bootstrapData = getBootstrapData(); const menu = { ...bootstrapData.common.menu_data }; diff --git a/superset-frontend/src/views/store.ts b/superset-frontend/src/views/store.ts index a143deb7379fd..9fe1443bf9529 100644 --- a/superset-frontend/src/views/store.ts +++ b/superset-frontend/src/views/store.ts @@ -16,16 +16,8 @@ * specific language governing permissions and limitations * under the License. */ -import { - applyMiddleware, - combineReducers, - compose, - createStore, - Store, -} from 'redux'; -import thunk from 'redux-thunk'; +import { configureStore, ConfigureStoreOptions, Store } from '@reduxjs/toolkit'; import messageToastReducer from 'src/components/MessageToasts/reducers'; -import { initEnhancer } from 'src/reduxUtils'; import charts from 'src/components/Chart/chartReducer'; import dataMask from 'src/dataMask/reducer'; import reports from 'src/reports/reducers/reports'; @@ -102,8 +94,7 @@ const CombinedDatasourceReducers = ( ); }; -// exported for tests -export const rootReducer = combineReducers({ +const reducers = { messageToasts: messageToastReducer, common: noopReducer(bootstrapData.common), user: userReducer, @@ -120,13 +111,7 @@ export const rootReducer = combineReducers({ reports, saveModal, explore, -}); - -export const store: Store = createStore( - rootReducer, - {}, - compose(applyMiddleware(thunk, logger), initEnhancer(false)), -); +}; /* In some cases the jinja template injects two seperate React apps into basic.html * One for the top navigation Menu and one for the application below the Menu @@ -135,13 +120,36 @@ export const store: Store = createStore( * setupStore with disableDebugger true enables the menu.tsx component to avoid connecting * to redux debugger so the application can connect to redux debugger */ -export function setupStore(disableDegugger = false): Store { - return createStore( - rootReducer, - {}, - compose( - applyMiddleware(thunk, logger), - initEnhancer(false, undefined, disableDegugger), - ), - ); +export function setupStore({ + disableDebugger = false, + initialState = {}, + rootReducers = reducers, + ...overrides +}: { + disableDebugger?: boolean; + initialState?: ConfigureStoreOptions['preloadedState']; + rootReducers?: ConfigureStoreOptions['reducer']; +} & Partial = {}): Store { + return configureStore({ + preloadedState: initialState, + reducer: { + ...rootReducers, + }, + middleware: getDefaultMiddleware => + getDefaultMiddleware({ + immutableCheck: { + warnAfter: 200, + }, + serializableCheck: { + // Ignores AbortController instances + ignoredActionPaths: [/queryController/g], + ignoredPaths: [/queryController/g], + warnAfter: 200, + }, + }).concat(logger), + devTools: process.env.WEBPACK_MODE === 'development' && !disableDebugger, + ...overrides, + }); } + +export const store: Store = setupStore();