diff --git a/package.json b/package.json index 9431724a..26373a29 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "@pybricks/firmware": "4.15.0", "@pybricks/ide-docs": "2.2.0", "@pybricks/mpy-cross-v5": "^2.0.0", + "@reduxjs/toolkit": "^1.8.2", "@shopify/react-i18n": "^7.1.3", "@svgr/webpack": "^6.2.1", "@testing-library/dom": "^8.13.0", diff --git a/src/index.tsx b/src/index.tsx index 1e585b35..92ee13a1 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -3,12 +3,12 @@ import './index.scss'; import { HotkeysProvider } from '@blueprintjs/core'; +import { configureStore } from '@reduxjs/toolkit'; import { I18nContext } from '@shopify/react-i18n'; import React from 'react'; import { OverlayProvider } from 'react-aria'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; -import { applyMiddleware, createStore } from 'redux'; import { createLogger } from 'redux-logger'; import createSagaMiddleware from 'redux-saga'; import App from './app/App'; @@ -38,10 +38,24 @@ const sagaMiddleware = createSagaMiddleware({ // TODO: add runtime option or filter - logger affects firmware flash performance const loggerMiddleware = createLogger({ predicate: () => false }); -const store = createStore( - rootReducer, - applyMiddleware(sagaMiddleware, loggerMiddleware), -); +const store = configureStore({ + reducer: rootReducer, + middleware: (getDefaultMiddleware) => + getDefaultMiddleware({ + serializableCheck: { + ignoredActionPaths: [ + // copy of defaults + 'meta.arg', + 'meta.baseQueryMeta', + // HACK: technically serializable, can be removed after + // https://github.com/microsoft/vscode/pull/151993 + 'viewState.viewState.firstPosition', + ], + }, + }) + .concat(sagaMiddleware) + .concat(loggerMiddleware), +}); // special styling for beta versions if (appVersion.match(/beta/)) { diff --git a/test/index.tsx b/test/index.tsx index 8ea605f8..a4f6d9ba 100644 --- a/test/index.tsx +++ b/test/index.tsx @@ -2,13 +2,19 @@ // Copyright (c) 2020-2022 The Pybricks Authors import { HotkeysProvider } from '@blueprintjs/core'; +import { ThunkAction, configureStore } from '@reduxjs/toolkit'; import { I18nContext, I18nManager } from '@shopify/react-i18n'; import { RenderResult, render } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import type { UserEvent } from '@testing-library/user-event/dist/types/setup'; import React, { ReactElement } from 'react'; import { Provider } from 'react-redux'; -import { AnyAction, DeepPartial, PreloadedState, createStore } from 'redux'; +import { + AnyAction, + DeepPartial, + PreloadedState, + legacy_createStore as createStore, +} from 'redux'; import { END, MulticastChannel, Saga, Task, runSaga, stdChannel } from 'redux-saga'; import { UUID } from '../src/fileStorage'; import { RootState, rootReducer } from '../src/reducers'; @@ -143,9 +149,28 @@ export function lookup(obj: unknown, id: string): string | undefined { export const testRender = ( component: ReactElement, state?: PreloadedState, -): [UserEvent, RenderResult, jest.SpyInstance] => { +): [ + UserEvent, + RenderResult, + jest.SpyInstance< + unknown, + [ + action: + | AnyAction + | ThunkAction< + unknown, + ReturnType, + undefined, + AnyAction + >, + ] + >, +] => { const user = userEvent.setup(); - const store = createStore(rootReducer, state); + const store = configureStore({ + reducer: rootReducer, + preloadedState: state, + }); const dispatch = jest.spyOn(store, 'dispatch'); const i18n = new I18nManager({ locale: 'en' }); diff --git a/yarn.lock b/yarn.lock index 6380f1b5..7d0d78c5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2294,6 +2294,7 @@ __metadata: "@pybricks/firmware": 4.15.0 "@pybricks/ide-docs": 2.2.0 "@pybricks/mpy-cross-v5": ^2.0.0 + "@reduxjs/toolkit": ^1.8.2 "@shopify/react-i18n": ^7.1.3 "@svgr/webpack": ^6.2.1 "@testing-library/dom": ^8.13.0 @@ -3636,6 +3637,26 @@ __metadata: languageName: node linkType: hard +"@reduxjs/toolkit@npm:^1.8.2": + version: 1.8.2 + resolution: "@reduxjs/toolkit@npm:1.8.2" + dependencies: + immer: ^9.0.7 + redux: ^4.1.2 + redux-thunk: ^2.4.1 + reselect: ^4.1.5 + peerDependencies: + react: ^16.9.0 || ^17.0.0 || ^18 + react-redux: ^7.2.1 || ^8.0.0-beta + peerDependenciesMeta: + react: + optional: true + react-redux: + optional: true + checksum: bd94e6d5c469f841c59e7d74e3fc60681c023ccdc6367005a9b04c252990d103bba438b2aea82f6e3db697486b32f4a5fb0d4bb6208af6119e5028c2ee626198 + languageName: node + linkType: hard + "@rollup/plugin-babel@npm:^5.2.0": version: 5.3.1 resolution: "@rollup/plugin-babel@npm:5.3.1" @@ -12742,7 +12763,16 @@ __metadata: languageName: node linkType: hard -"redux@npm:^4.0.0, redux@npm:^4.0.4, redux@npm:^4.2.0": +"redux-thunk@npm:^2.4.1": + version: 2.4.1 + resolution: "redux-thunk@npm:2.4.1" + peerDependencies: + redux: ^4 + checksum: af5abb425fb9dccda02e5f387d6f3003997f62d906542a3d35fc9420088f550dc1a018bdc246c7d23ee852b4d4ab8b5c64c5be426e45a328d791c4586a3c6b6e + languageName: node + linkType: hard + +"redux@npm:^4.0.0, redux@npm:^4.0.4, redux@npm:^4.1.2, redux@npm:^4.2.0": version: 4.2.0 resolution: "redux@npm:4.2.0" dependencies: @@ -12881,6 +12911,13 @@ __metadata: languageName: node linkType: hard +"reselect@npm:^4.1.5": + version: 4.1.6 + resolution: "reselect@npm:4.1.6" + checksum: 3ea1058422904063ec93c8f4693fe33dcb2178bbf417ace8db5b2c797a5875cf357d9308d11ed3942ee22507dd34ecfbf1f3a21340a4f31c206cab1d36ceef31 + languageName: node + linkType: hard + "resolve-cwd@npm:^3.0.0": version: 3.0.0 resolution: "resolve-cwd@npm:3.0.0"