diff --git a/packages/runtime/package.json b/packages/runtime/package.json index e5591948f..4f90726be 100644 --- a/packages/runtime/package.json +++ b/packages/runtime/package.json @@ -124,6 +124,7 @@ "@emotion/utils": "^1.0.0", "@makeswift/next-plugin": "0.2.8", "@popmotion/popcorn": "^0.4.4", + "@reduxjs/toolkit": "^1.9.5", "@types/cookie": "^0.5.1", "@types/http-proxy": "^1.17.9", "@types/is-hotkey": "^0.1.7", @@ -150,8 +151,6 @@ "path-to-regexp": "^6.2.1", "polished": "3.0.3", "react-player": "^1.12.0", - "redux": "^4.0.5", - "redux-thunk": "^2.3.0", "scroll-into-view-if-needed": "^2.2.20", "set-cookie-parser": "^2.5.1", "slate": "^0.91.4", diff --git a/packages/runtime/src/state/actions.ts b/packages/runtime/src/state/actions.ts index df68e59ca..e97332006 100644 --- a/packages/runtime/src/state/actions.ts +++ b/packages/runtime/src/state/actions.ts @@ -3,7 +3,7 @@ import type { Operation } from 'ot-json0' import type { Document } from './modules/read-only-documents' import type { ComponentType } from './modules/react-components' import type { Measurable, BoxModel } from './modules/box-models' -import type { ThunkAction } from 'redux-thunk' +import type { ThunkAction } from '@reduxjs/toolkit' import { ComponentMeta } from './modules/components-meta' import { PropControllerDescriptor } from '../prop-controllers' import type { Size } from './react-builder-preview' diff --git a/packages/runtime/src/state/makeswift-api-client.ts b/packages/runtime/src/state/makeswift-api-client.ts index 81c63b8e7..9b8a16a3e 100644 --- a/packages/runtime/src/state/makeswift-api-client.ts +++ b/packages/runtime/src/state/makeswift-api-client.ts @@ -1,5 +1,4 @@ -import { applyMiddleware, createStore, Store as ReduxStore } from 'redux' -import thunk, { ThunkAction, ThunkDispatch } from 'redux-thunk' +import { configureStore as configureReduxStore, ThunkAction } from '@reduxjs/toolkit' import * as APIResources from './modules/api-resources' import { Action, apiResourceFulfilled } from './actions' @@ -113,10 +112,13 @@ export function fetchAPIResource( } } -export type Dispatch = ThunkDispatch +export function configureStore({ serializedState }: { serializedState?: SerializedState }) { + return configureReduxStore({ + reducer, + preloadedState: APIResources.getInitialState(serializedState), + }) +} -export type Store = ReduxStore & { dispatch: Dispatch } +export type Store = ReturnType -export function configureStore({ serializedState }: { serializedState?: SerializedState }): Store { - return createStore(reducer, APIResources.getInitialState(serializedState), applyMiddleware(thunk)) -} +export type Dispatch = Store['dispatch'] diff --git a/packages/runtime/src/state/react-builder-preview.ts b/packages/runtime/src/state/react-builder-preview.ts index 068a06847..7a274b0d6 100644 --- a/packages/runtime/src/state/react-builder-preview.ts +++ b/packages/runtime/src/state/react-builder-preview.ts @@ -1,15 +1,13 @@ +import Router from 'next/router' import { - applyMiddleware, combineReducers, - createStore, - Dispatch as ReduxDispatch, + configureStore as configureReduxStore, Middleware, MiddlewareAPI, PreloadedState, - Store as ReduxStore, -} from 'redux' -import thunk, { ThunkAction, ThunkDispatch } from 'redux-thunk' -import Router from 'next/router' + ThunkAction, + Dispatch as ReduxDispatch, +} from '@reduxjs/toolkit' import deepEqual from '../utils/deepEqual' @@ -434,10 +432,12 @@ export function initialize(): ThunkAction<() => void, State, unknown, Action> { } } -export type Dispatch = ThunkDispatch - -function measureBoxModelsMiddleware(): Middleware { - return ({ dispatch }: MiddlewareAPI) => +function measureBoxModelsMiddleware(): Middleware< + ReduxDispatch, + State, + ReduxDispatch +> { + return ({ dispatch }: MiddlewareAPI>) => (next: ReduxDispatch) => { return (action: Action): Action => { switch (action.type) { @@ -465,7 +465,11 @@ function measureBoxModelsMiddleware(): Middleware { } } -export function messageChannelMiddleware(): Middleware { +export function messageChannelMiddleware(): Middleware< + ReduxDispatch, + State, + ReduxDispatch +> { return ({ dispatch, getState }: MiddlewareAPI) => (next: ReduxDispatch) => { let cleanUp = () => {} @@ -614,7 +618,11 @@ function createAndRegisterPropControllers( } } -function propControllerHandlesMiddleware(): Middleware { +function propControllerHandlesMiddleware(): Middleware< + ReduxDispatch, + State, + ReduxDispatch +> { return ({ dispatch, getState }: MiddlewareAPI) => (next: ReduxDispatch) => { return (action: Action): Action => { @@ -678,7 +686,12 @@ if (import.meta.vitest) { // Arrange const documentKey = 'documentKey' const element: ReactPage.Element = { key: 'elementKey', type: 'type', props: {} } - const store = createStore(reducer, applyMiddleware(thunk, propControllerHandlesMiddleware())) + const store = configureReduxStore({ + reducer, + middleware(getDefaultMiddleware) { + return getDefaultMiddleware().concat(propControllerHandlesMiddleware()) + }, + }) const setPropControllers = fn() const handle = new ElementImperativeHandle() @@ -697,7 +710,12 @@ if (import.meta.vitest) { // Arrange const documentKey = 'documentKey' const element: ReactPage.Element = { type: 'reference', key: 'elementKey', value: 'value' } - const store = createStore(reducer, applyMiddleware(thunk, propControllerHandlesMiddleware())) + const store = configureReduxStore({ + reducer, + middleware(getDefaultMiddleware) { + return getDefaultMiddleware().concat(propControllerHandlesMiddleware()) + }, + }) const setPropControllers = fn() const handle = new ElementImperativeHandle() @@ -716,7 +734,7 @@ if (import.meta.vitest) { function makeswiftApiClientSyncMiddleware( client: MakeswiftClient, -): Middleware { +): Middleware, State, ReduxDispatch> { return () => (next: ReduxDispatch) => { return (action: Action): Action => { client.makeswiftApiClient.dispatch(action) @@ -726,8 +744,6 @@ function makeswiftApiClientSyncMiddleware( } } -export type Store = ReduxStore & { dispatch: Dispatch } - export function configureStore({ rootElements, preloadedState, @@ -736,22 +752,27 @@ export function configureStore({ rootElements?: Map preloadedState?: PreloadedState client: MakeswiftClient -}): Store { +}) { const initialState: PreloadedState = { ...preloadedState, documents: Documents.getInitialState({ rootElements }), isPreview: IsPreview.getInitialState(true), } - return createStore( + return configureReduxStore({ reducer, - initialState, - applyMiddleware( - thunk, - measureBoxModelsMiddleware(), - messageChannelMiddleware(), - propControllerHandlesMiddleware(), - makeswiftApiClientSyncMiddleware(client), - ), - ) + preloadedState: initialState, + middleware(getDefaultMiddleware) { + return getDefaultMiddleware().concat([ + measureBoxModelsMiddleware(), + messageChannelMiddleware(), + propControllerHandlesMiddleware(), + makeswiftApiClientSyncMiddleware(client), + ]) + }, + }) } + +export type Store = ReturnType + +export type Dispatch = Store['dispatch'] diff --git a/packages/runtime/src/state/react-page.ts b/packages/runtime/src/state/react-page.ts index 997163949..f753f83ee 100644 --- a/packages/runtime/src/state/react-page.ts +++ b/packages/runtime/src/state/react-page.ts @@ -1,11 +1,8 @@ import { - applyMiddleware, combineReducers, - createStore, + configureStore as configureReduxStore, PreloadedState, - Store as ReduxStore, -} from 'redux' -import thunk, { ThunkDispatch } from 'redux-thunk' +} from '@reduxjs/toolkit' import * as Documents from './modules/read-only-documents' import * as ReactComponents from './modules/react-components' @@ -18,7 +15,6 @@ import * as BuilderEditMode from './modules/builder-edit-mode' import * as Breakpoints from './modules/breakpoints' import * as Locales from './modules/locales' import * as Introspection from '../prop-controllers/introspection' -import { Action } from './actions' import { copyElementReference } from '../prop-controllers/copy' import { copy as copyFromControl, merge } from '../controls/control' @@ -396,10 +392,6 @@ export function getDefaultLocale(state: State): Intl.Locale | null { return state.locales.defaultLocale ? new Intl.Locale(state.locales.defaultLocale) : null } -export type Dispatch = ThunkDispatch - -export type Store = ReduxStore & { dispatch: Dispatch } - export function configureStore({ rootElements, preloadedState, @@ -410,15 +402,21 @@ export function configureStore({ preloadedState?: PreloadedState breakpoints?: Breakpoints.State locales?: Locales.State -} = {}): Store { - return createStore( +} = {}) { + return configureReduxStore({ reducer, - { + preloadedState: { ...preloadedState, documents: Documents.getInitialState({ rootElements }), breakpoints: Breakpoints.getInitialState(breakpoints ?? preloadedState?.breakpoints), locales: Locales.getInitialState(locales ?? preloadedState?.locales), }, - applyMiddleware(thunk), - ) + middleware(getDefaultMiddleware) { + return getDefaultMiddleware() + }, + }) } + +export type Store = ReturnType + +export type Dispatch = Store['dispatch'] diff --git a/yarn.lock b/yarn.lock index 0c58460f2..f646a55a5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2437,6 +2437,16 @@ style-value-types "^3.1.7" tslib "^1.10.0" +"@reduxjs/toolkit@^1.9.5": + version "1.9.5" + resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-1.9.5.tgz#d3987849c24189ca483baa7aa59386c8e52077c4" + integrity sha512-Rt97jHmfTeaxL4swLRNPD/zV4OxTes4la07Xc4hetpUW/vc75t5m1ANyxG6ymnEQ2FsLQsoMlYB2vV1sO3m8tQ== + dependencies: + immer "^9.0.21" + redux "^4.2.1" + redux-thunk "^2.4.2" + reselect "^4.1.8" + "@rollup/pluginutils@^4.1.2": version "4.2.0" resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.2.0.tgz#a14bbd058fdbba0a5647143b16ed0d86fb60bd08" @@ -5418,6 +5428,11 @@ ignore@^5.2.0: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== +immer@^9.0.21: + version "9.0.21" + resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.21.tgz#1e025ea31a40f24fb064f1fef23e931496330176" + integrity sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA== + immer@^9.0.6: version "9.0.19" resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.19.tgz#67fb97310555690b5f9cd8380d38fc0aabb6b38b" @@ -7733,15 +7748,15 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" -redux-thunk@^2.3.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.4.1.tgz#0dd8042cf47868f4b29699941de03c9301a75714" - integrity sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q== +redux-thunk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.4.2.tgz#b9d05d11994b99f7a91ea223e8b04cf0afa5ef3b" + integrity sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q== -redux@^4.0.5: - version "4.1.2" - resolved "https://registry.yarnpkg.com/redux/-/redux-4.1.2.tgz#140f35426d99bb4729af760afcf79eaaac407104" - integrity sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw== +redux@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197" + integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w== dependencies: "@babel/runtime" "^7.9.2" @@ -7887,6 +7902,11 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== +reselect@^4.1.8: + version "4.1.8" + resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.8.tgz#3f5dc671ea168dccdeb3e141236f69f02eaec524" + integrity sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ== + resolve-cwd@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d"