Skip to content

Chore: Migrate to Redux Toolkit#1622

Merged
jumpinjackie merged 10 commits intomasterfrom
copilot/migrate-to-redux-toolkit
Apr 7, 2026
Merged

Chore: Migrate to Redux Toolkit#1622
jumpinjackie merged 10 commits intomasterfrom
copilot/migrate-to-redux-toolkit

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 5, 2026

Replaces the legacy redux + redux-thunk + redux-logger stack with @reduxjs/toolkit, which bundles all three and adds DevTools integration out of the box.

Package changes

  • Added @reduxjs/toolkit ^2.11.2
  • Removed redux, redux-thunk, redux-logger

src/store/configure-store.ts

Replaced manual createStore + compose + applyMiddleware wiring with RTK's configureStore. Thunk and DevTools are now handled automatically. Serializability and immutability invariant checks are disabled to preserve compatibility with the existing non-serializable Redux state.

// Before
const store = compose(_getMiddleware(), ..._getEnhancers())(createStore)(root, initialState);

// After
return rtkConfigureStore({
    reducer: combineReducers(rootReducerMap),
    preloadedState: initialState,
    middleware: (getDefaultMiddleware) => {
        const base = getDefaultMiddleware({ serializableCheck: false, immutableStateInvariant: false })
            .prepend(promiseMiddleware as any);
        return isDev ? base.concat(logger as any) : base;
    },
    devTools: isDev,
});

src/store/logger.ts

redux-logger's createLogger replaced with a hand-rolled Middleware that preserves identical filtering behaviour (same FILTERED_TYPES set) using RTK's Middleware type.

Import updates

  • Action and Dispatch imports in src/actions/defs.ts and src/layouts/hooks.ts updated from 'redux''@reduxjs/toolkit' (re-exported by RTK).
  • Same update applied to Store type imports in test files.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • storybook.js.org
    • Triggering command: /opt/hostedtoolcache/node/24.14.1/x64/bin/node /opt/hostedtoolcache/node/24.14.1/x64/bin/node /home/REDACTED/work/mapguide-react-layout/mapguide-react-layout/node_modules/.bin/storybook build -c .storybook (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI linked an issue Apr 5, 2026 that may be closed by this pull request
Copilot AI changed the title [WIP] Chore: Migrate from Redux to Redux Toolkit Chore: Migrate to Redux Toolkit Apr 5, 2026
Copilot AI requested a review from jumpinjackie April 5, 2026 17:47
@jumpinjackie jumpinjackie requested a review from Copilot April 5, 2026 17:48
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 5, 2026

Bundle Size Report ✅ PASS

Metric Size Gzip Brotli
Total 12.02 MB 2.56 MB 1.83 MB
Diff +153.48 KB 🔴 ↑ +36.02 KB 🔴 ↑ +35.66 KB 🔴 ↑
Change +1.26% +1.39% +1.94%

Top Changes

File Before After Diff
~ vendor-debug.js 1.01 MB 1.04 MB +27.21 KB 🔴 ↑
~ vendor.js 425.47 KB 433.58 KB +8.10 KB 🔴 ↑
~ viewer-debug.js 198.92 KB 199.21 KB +302.00 B 🔴 ↑
~ viewer.js 122.43 KB 122.49 KB +55.00 B 🔴 ↑

Generated by build-size-diff Commit: e2c9f9d

@coveralls
Copy link
Copy Markdown

coveralls commented Apr 5, 2026

Coverage Status

coverage: 41.219% (+0.04%) from 41.179% — copilot/migrate-to-redux-toolkit into master

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Migrates the project’s Redux store setup from the legacy redux + redux-thunk + redux-logger wiring to Redux Toolkit (@reduxjs/toolkit), simplifying store configuration and aligning middleware/devtools integration with RTK conventions.

Changes:

  • Replaced manual store creation with RTK configureStore (including custom middleware ordering and devtools handling).
  • Replaced redux-logger with a custom RTK Middleware implementation that preserves the existing filtered-action behavior.
  • Updated Redux-related type imports in app code and tests to use RTK re-exports.

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
package.json Adds @reduxjs/toolkit, removes direct redux* deps.
yarn.lock Locks RTK + transitive deps; removes redux-logger/deep-diff; introduces Redux v5 via RTK.
src/store/configure-store.ts Moves store setup to RTK configureStore, customizes default middleware and devtools.
src/store/logger.ts Implements a custom logger middleware and preserves action-type filtering.
src/actions/defs.ts Switches Action type import to RTK re-export.
src/layouts/hooks.ts Switches Dispatch type import to RTK re-export.
src/components/map-providers/context.tsx Updates comment to reflect RTK-enhanced dispatch typing.
test/store/configure-store.spec.ts Updates Store type import to RTK re-export.
test/store/logger.spec.ts Updates test store creation to RTK configureStore.
test/containers/hooks.spec.tsx Updates Store type import to RTK re-export.
Comments suppressed due to low confidence (1)

test/store/logger.spec.ts:26

  • This test exercises the middleware but doesn’t assert that logging happens for non-filtered actions (it only ensures nothing throws). Since redux-logger was replaced with a custom implementation, add at least one assertion (e.g., console.groupCollapsed/console.log called) to prevent silent regressions in the new logger behavior.
        it("passes action through and calls stateTransformer and predicate for regular actions", () => {
            // Suppress console output during test
            const consoleSpy = vi.spyOn(console, "group").mockImplementation(() => {});
            const consoleLogSpy = vi.spyOn(console, "log").mockImplementation(() => {});
            const consoleGroupCollapsed = vi.spyOn(console, "groupCollapsed").mockImplementation(() => {});
            const consoleGroupEnd = vi.spyOn(console, "groupEnd").mockImplementation(() => {});

            const store = configureStore({ reducer, middleware: () => [logger] as any });
            // Dispatch a non-filtered action type
            store.dispatch({ type: "TEST_ACTION", payload: {} });
            // No assertion needed - just ensuring predicate and stateTransformer get called

jumpinjackie and others added 5 commits April 6, 2026 03:53
@jumpinjackie
Copy link
Copy Markdown
Owner

@copilot There is a whole lot of TS errors. Pls fix:

src/containers/app.tsx:310:90 - error TS2345: Argument of type 'ReduxThunkedAction' is not assignable to parameter of type 'AnyAction'.

310     const initLayoutAction = (cmd: IViewerInitCommand, args: IInitAppLayout) => dispatch(initLayout(cmd, viewer, args));
                                                                                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

src/containers/flyout-region.tsx:18:79 - error TS2345: Argument of type 'ReduxThunkedAction' is not assignable to parameter of type 'AnyAction'.

18     const invokeCommandAction = (cmd: ICommand, parameters?: any) => dispatch(invokeCommand(cmd, viewer, parameters));
                                                                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

src/containers/legend.tsx:71:18 - error TS2345: Argument of type 'ReduxThunkedAction' is not assignable to parameter of type 'AnyAction'.

71         dispatch(refresh());
                    ~~~~~~~~~

src/containers/map-menu.tsx:12:62 - error TS2345: Argument of type 'ReduxThunkedAction' is not assignable to parameter of type 'AnyAction'.

12     const onActiveMapChanged = (mapName: string) => dispatch(activateMap(mapName));
                                                                ~~~~~~~~~~~~~~~~~~~~

src/containers/navigator.tsx:24:79 - error TS2345: Argument of type 'ReduxThunkedAction' is not assignable to parameter of type 'AnyAction'.

24     const invokeCommandAction = (cmd: ICommand, parameters?: any) => dispatch(invokeCommand(cmd, viewer, parameters));
                                                                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

src/containers/selection-panel.tsx:28:63 - error TS2345: Argument of type 'ReduxThunkedAction' is not assignable to parameter of type 'AnyAction'.

28     const setCurrentViewAction = (view: IMapView) => dispatch(setCurrentView(view));
                                                                 ~~~~~~~~~~~~~~~~~~~~

src/containers/task-pane.tsx:42:41 - error TS2345: Argument of type 'ReduxThunkedAction' is not assignable to parameter of type 'AnyAction'.

42     const goHomeAction = () => dispatch(goHome());
                                           ~~~~~~~~

src/containers/toolbar.tsx:31:78 - error TS2345: Argument of type 'ReduxThunkedAction' is not assignable to parameter of type 'AnyAction'.

31     const invokeCommandAction = (cmd: ICommand, parameters: any) => dispatch(invokeCommand(cmd, viewer, parameters));
                                                                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

src/containers/viewer-shim.tsx:1258:41 - error TS2345: Argument of type 'ReduxThunkedAction' is not assignable to parameter of type 'AnyAction'.

1258     const goHomeAction = () => dispatch(goHome());
                                             ~~~~~~~~

src/containers/viewer-shim.tsx:1259:42 - error TS2345: Argument of type 'ReduxThunkedAction' is not assignable to parameter of type 'AnyAction'.

1259     const legendRefresh = () => dispatch(refresh());
                                              ~~~~~~~~~

src/containers/viewer-shim.tsx:1260:78 - error TS2345: Argument of type 'ReduxThunkedAction' is not assignable to parameter of type 'AnyAction'.

1260     const invokeCommandAction = (cmd: ICommand, parameters: any) => dispatch(invokeCommand(cmd, viewer, parameters));
                                                                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

src/containers/viewer-shim.tsx:1262:105 - error TS2345: Argument of type 'ReduxThunkedAction' is not assignable to parameter of type 'AnyAction'.

1262     const queryMapFeaturesAction = (mapName: string, options: QueryMapFeatureActionOptions) => dispatch(queryMapFeatures(mapName, options));

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 5, 2026

@copilot There is a whole lot of TS errors. Pls fix:

...

Fixed in commit 8924f57. The root cause was useDispatch() from react-redux returning Dispatch<AnyAction> which doesn't accept thunk functions. Here's what was changed:

  1. Upgraded react-redux v7 → v8 and removed @types/react-redux (react-redux v8 ships its own types and is compatible with Redux v5 bundled by RTK).
  2. useReduxDispatch() now returns ReduxDispatch — cast from useDispatch() with a comment explaining why the double cast is necessary (the types are structurally incompatible at the TypeScript level, but at runtime RTK's thunk middleware correctly handles both plain actions and thunks).
  3. CommonTemplateState.dispatch in src/layouts/hooks.ts updated from Dispatch<any>ReduxDispatch.
  4. externalLayersReady() in src/actions/map.ts given an explicit IExternalLayersReadyAction return type to fix narrowing from the broad ActionType enum to the specific literal ActionType.EXTERNAL_LAYERS_READY.

- Introduced sessionWasReused property in IConfigurationReducerState and related interfaces.
- Updated configReducer to handle sessionWasReused during initialization.
- Modified activateMap thunk to conditionally describe existing maps based on session reuse.
- Enhanced tests to verify sessionWasReused behavior in INIT_APP action.
@jumpinjackie jumpinjackie marked this pull request as ready for review April 7, 2026 11:13
@jumpinjackie jumpinjackie merged commit 4ffc6ef into master Apr 7, 2026
5 checks passed
@jumpinjackie jumpinjackie deleted the copilot/migrate-to-redux-toolkit branch April 7, 2026 11:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Chore: Migrate to Redux Toolkit

4 participants