@@ -42,11 +44,12 @@ export function reduxRenderStart(options) {
// onLoadStartElement - the HTML element to render into upon loaded by the browser
//
export function reduxLoadSubApp(info) {
- const renderStart = function(instance, element) {
+ const renderStart = function (instance, element) {
const initialState = instance._prepared || instance.initialState;
- const reduxCreateStore = instance.reduxCreateStore || this.info.reduxCreateStore;
+ const reduxCreateStore =
+ instance.reduxCreateStore || this.info.reduxCreateStore;
const Component = this.info.StartComponent || this.info.Component;
- const props = instance.props || {}
+ const props = instance.props || {};
const { store, subappRoot } = reduxRenderStart({
_store: instance._store,
@@ -55,7 +58,7 @@ export function reduxLoadSubApp(info) {
Component,
serverSideRendering: instance.serverSideRendering,
element,
- props
+ props,
});
instance._store = store;
@@ -64,7 +67,7 @@ export function reduxLoadSubApp(info) {
};
const extras = {
- __redux: true
+ __redux: true,
};
if (!info.reduxCreateStore) {
@@ -73,7 +76,7 @@ export function reduxLoadSubApp(info) {
return loadSubApp(
Object.assign(extras, info, {
- reduxCreateStore: getReduxCreateStore(info)
+ reduxCreateStore: getReduxCreateStore(info),
}),
renderStart
);
diff --git a/packages/subapp-redux/src/shared.js b/packages/subapp-redux/src/shared.js
index 1149ef087..3e7b2f137 100644
--- a/packages/subapp-redux/src/shared.js
+++ b/packages/subapp-redux/src/shared.js
@@ -1,4 +1,4 @@
-import { createStore, combineReducers } from "redux";
+import { configureStore, combineReducers } from "@reduxjs/toolkit";
//
// - stores can be shared between subapps with reduxShareStore flag
@@ -75,7 +75,10 @@ const combineSharedReducers = (info, container, reducers) => {
};
function replaceReducer(newReducers, info, storeContainer) {
- let { store, reducerContainer } = getSharedStore(info.reduxShareStore, storeContainer);
+ let { store, reducerContainer } = getSharedStore(
+ info.reduxShareStore,
+ storeContainer
+ );
const reducer = combineSharedReducers(info, reducerContainer, newReducers);
return store[originalReplaceReducerSym](reducer);
}
@@ -88,25 +91,27 @@ function createSharedStore(initialState, info, storeContainer) {
info._genReduxCreateStore || !info.reduxCreateStore,
`${WHEN_SHARED_MSG}, you cannot have reduxCreateStore`
);
- let { store, reducerContainer } = getSharedStore(sharedStoreName, storeContainer);
+ let { store, reducerContainer } = getSharedStore(
+ sharedStoreName,
+ storeContainer
+ );
if (store) {
// TODO: redux doesn't have a way to set initial state
// after store's created? What can we do about this?
replaceReducer(info.reduxReducers, info, storeContainer);
} else {
reducerContainer = newReducerContainer();
- if (info.reduxEnhancer && info.reduxEnhancer instanceof Function) {
- store = createStore(
- combineSharedReducers(info, reducerContainer, info.reduxReducers),
- initialState,
- info.reduxEnhancer()
- );
- } else {
- store = createStore(
- combineSharedReducers(info, reducerContainer, info.reduxReducers),
- initialState
- );
- }
+ store = configureStore({
+ reducer: combineSharedReducers(
+ info,
+ reducerContainer,
+ info.reduxReducers
+ ),
+ preloadedState: initialState,
+ enhancers: info.reduxEnhancer,
+ middleware: info.middleware,
+ });
+
store[originalReplaceReducerSym] = store.replaceReducer;
//
// TODO: better handling of a replaceReducer that takes extra params
@@ -124,7 +129,11 @@ function createSharedStore(initialState, info, storeContainer) {
return replaceReducer(reducers, info2, storeContainer2);
};
}
- setSharedStore(sharedStoreName, { store, reducerContainer }, storeContainer);
+ setSharedStore(
+ sharedStoreName,
+ { store, reducerContainer },
+ storeContainer
+ );
return store;
}
@@ -142,17 +151,20 @@ function createSharedStore(initialState, info, storeContainer) {
} else if (reducerType === "object") {
reducer = combineReducers(info.reduxReducers);
} else {
- reducer = x => x;
+ reducer = (x) => x;
}
- if (info.reduxEnhancer && info.reduxEnhancer instanceof Function) {
- return createStore(reducer, initialState, info.reduxEnhancer());
- }
- return createStore(reducer, initialState);
+ return configureStore({
+ reducer,
+ preloadedState: initialState,
+ enhancers: info.reduxEnhancer,
+ middleware: info.middleware,
+ });
}
function getReduxCreateStore(info) {
- return (initialState, storeContainer) => createSharedStore(initialState, info, storeContainer);
+ return (initialState, storeContainer) =>
+ createSharedStore(initialState, info, storeContainer);
}
export {
@@ -161,5 +173,5 @@ export {
createSharedStore,
getSharedStore,
setSharedStore,
- clearSharedStore
+ clearSharedStore,
};
diff --git a/packages/subapp-redux/test/spec/index.spec.js b/packages/subapp-redux/test/spec/index.spec.js
index bb7caa0c0..53f582a52 100644
--- a/packages/subapp-redux/test/spec/index.spec.js
+++ b/packages/subapp-redux/test/spec/index.spec.js
@@ -1,12 +1,16 @@
"use strict";
const subappRedux = require("../..");
-const { getReduxCreateStore, clearSharedStore, setStoreContainer } = require("../../src/shared");
+const {
+ getReduxCreateStore,
+ clearSharedStore,
+ setStoreContainer,
+} = require("../../src/shared");
const { getSubAppContainer } = require("subapp-util");
const SimpleReducer = (x = true) => x;
-describe("subapp-redux", function() {
+describe("subapp-redux", function () {
afterEach(() => {
clearSharedStore();
});
@@ -18,7 +22,7 @@ describe("subapp-redux", function() {
it("should create store based on reduxCreateStore if it is passed", () => {
const store = getReduxCreateStore({
- reduxCreateStore: () => 5
+ reduxCreateStore: () => 5,
})({});
expect(store).to.equal(5);
@@ -27,12 +31,12 @@ describe("subapp-redux", function() {
it("should use true reduxShareStore to name and persist primary store instance", () => {
const defaultStore = getReduxCreateStore({
reduxReducers: { a: SimpleReducer },
- reduxShareStore: true
+ reduxShareStore: true,
})({});
const defaultStore2 = getReduxCreateStore({
reduxReducers: { a: SimpleReducer },
- reduxShareStore: true
+ reduxShareStore: true,
})({});
expect(defaultStore).to.equal(defaultStore2);
@@ -41,12 +45,12 @@ describe("subapp-redux", function() {
it("should not conflate true reduxShareStore with named reduxShareStore", () => {
const defaultStore = getReduxCreateStore({
reduxReducers: { a: SimpleReducer },
- reduxShareStore: true
+ reduxShareStore: true,
})({});
const green = getReduxCreateStore({
reduxReducers: { a: SimpleReducer },
- reduxShareStore: "green"
+ reduxShareStore: "green",
})({});
expect(defaultStore).to.not.equal(green);
@@ -55,12 +59,12 @@ describe("subapp-redux", function() {
it("should use string reduxShareStore to name and persist store instances", () => {
const blue = getReduxCreateStore({
reduxReducers: { a: SimpleReducer },
- reduxShareStore: "blue"
+ reduxShareStore: "blue",
})({});
const blue2 = getReduxCreateStore({
reduxReducers: { a: SimpleReducer },
- reduxShareStore: "blue"
+ reduxShareStore: "blue",
})({});
expect(blue).to.equal(blue2);
@@ -69,12 +73,12 @@ describe("subapp-redux", function() {
it("should not conflate two different reduxShareStore keys", () => {
const blue = getReduxCreateStore({
reduxReducers: { a: SimpleReducer },
- reduxShareStore: "blue"
+ reduxShareStore: "blue",
})({});
const green = getReduxCreateStore({
reduxReducers: { a: SimpleReducer },
- reduxShareStore: "green"
+ reduxShareStore: "green",
})({});
expect(blue).to.not.equal(green);
@@ -84,7 +88,7 @@ describe("subapp-redux", function() {
expect(() =>
getReduxCreateStore({
reduxCreateStore: () => 5,
- reduxShareStore: true
+ reduxShareStore: true,
})({})
).throws("cannot have reduxCreateStore");
});
@@ -92,8 +96,8 @@ describe("subapp-redux", function() {
it("should not allow functional reducers in a shared store", () => {
expect(() => {
getReduxCreateStore({
- reduxReducers: x => x,
- reduxShareStore: true
+ reduxReducers: (x) => x,
+ reduxShareStore: true,
})({});
}).to.throw();
});
@@ -102,13 +106,13 @@ describe("subapp-redux", function() {
getReduxCreateStore({
name: "app1",
reduxReducers: { pi: (x = 3.146) => x },
- reduxShareStore: true
+ reduxShareStore: true,
})({});
const store = getReduxCreateStore({
name: "app2",
reduxReducers: { sqrt2: (x = 1.414) => x },
- reduxShareStore: true
+ reduxShareStore: true,
})({});
const state = store.getState();
@@ -120,7 +124,7 @@ describe("subapp-redux", function() {
getReduxCreateStore({
name: "app1",
reduxReducers: { pi: (x = 3.146) => x },
- reduxShareStore: true
+ reduxShareStore: true,
})({});
const app2 = {
@@ -128,9 +132,9 @@ describe("subapp-redux", function() {
reduxReducers: {
sqrt2: (x = 1.414) => {
return x;
- }
+ },
},
- reduxShareStore: true
+ reduxShareStore: true,
};
const store = getReduxCreateStore(app2)({});
@@ -141,11 +145,11 @@ describe("subapp-redux", function() {
{
sqrt2: () => {
return 11;
- }
+ },
},
app2
);
- store.dispatch({ type: 1 });
+ store.dispatch({ type: "1" });
const state2 = store.getState();
expect(state2.sqrt2).to.equal(11);
});
@@ -156,7 +160,7 @@ describe("subapp-redux", function() {
const store = getReduxCreateStore({
name: "app1",
reduxReducers: { pi: (x = 3.146) => x },
- reduxShareStore: true
+ reduxShareStore: true,
})({});
expect(container.namedStores._.store).equals(store);
@@ -169,7 +173,7 @@ describe("subapp-redux", function() {
name: "app",
reduxReducers: () => {
return { v: 1 };
- }
+ },
})({});
expect(container.namedStores).to.deep.equal({});
const state = store.getState();
@@ -184,8 +188,8 @@ describe("subapp-redux", function() {
reduxReducers: {
a: () => {
return 2;
- }
- }
+ },
+ },
})({});
expect(container.namedStores).to.deep.equal({});
const state = store.getState();
@@ -196,7 +200,7 @@ describe("subapp-redux", function() {
const container = {};
setStoreContainer(container);
const store = getReduxCreateStore({
- name: "app"
+ name: "app",
})({ a: 1 });
expect(container.namedStores).to.deep.equal({});
const state = store.getState();
diff --git a/samples/poc-subapp-redux/package.json b/samples/poc-subapp-redux/package.json
index c232f133f..e93e7c753 100644
--- a/samples/poc-subapp-redux/package.json
+++ b/samples/poc-subapp-redux/package.json
@@ -53,7 +53,8 @@
"subapp-react": "^1.3.0",
"subapp-redux": "^2.3.0",
"subapp-server": "^2.4.2",
- "subapp-web": "^2.1.6"
+ "subapp-web": "^2.1.6",
+ "@reduxjs/toolkit": ">= 2"
},
"devDependencies": {
"@xarc/app-dev": "^11.0.10",
@@ -64,4 +65,4 @@
"prettier": {
"printWidth": 100
}
-}
+}
\ No newline at end of file
diff --git a/samples/poc-subapp-redux/src/02.main-body/main-body.jsx b/samples/poc-subapp-redux/src/02.main-body/main-body.jsx
index 290e126d6..0ae01b4eb 100644
--- a/samples/poc-subapp-redux/src/02.main-body/main-body.jsx
+++ b/samples/poc-subapp-redux/src/02.main-body/main-body.jsx
@@ -2,14 +2,12 @@ import { reduxLoadSubApp } from "subapp-redux";
import { React } from "subapp-react";
import { connect } from "react-redux";
import { Route, Routes, BrowserRouter } from "react-router-dom";
-import logger from "redux-logger";
-import { applyMiddleware } from "redux";
import { Products } from "../components/products";
import { Deals } from "../components/deals";
import { Navigation } from "../components/navigation";
-import reduxReducers, { decNumber, incNumber } from "./reducers";
-
-
+import { reducers } from "../redux-store/reducers/root-reducer";
+import { decNumber, incNumber } from "../redux-store/actions/number-actions";
+import logger from "redux-logger";
const mapStateToProps = (state) => state;
const HomeComp = (props) => {
@@ -21,24 +19,25 @@ const HomeComp = (props) => {
return (
HOME
-
unmountSubapp({subappName: "Header" })}> Unmount Header
-
unmountSubapp({subappName: "Footer" })}> Unmount Footer
-
+
unmountSubapp({ subappName: "Header" })}> Unmount Header
+
unmountSubapp({ subappName: "Footer" })}> Unmount Footer
+
-
+
Redux State Demo
-
+
Check out the number below and footer's submit.
-
+
You can do the same on other tabs too, if available.
-
+
props.dispatch(decNumber())}>≪
- {props.number}
- props.dispatch(incNumber())}>≫
+
+ {props.numberReducer.number}
+ props.dispatch(incNumber())}>≫
+
-
);
};
@@ -46,7 +45,6 @@ const Stores = () => `Stores`;
const Contact = () => `Contact`;
const MainBody = (props) => {
-
return (
@@ -63,12 +61,13 @@ const MainBody = (props) => {
const Home = connect(mapStateToProps, (dispatch) => ({ dispatch }))(HomeComp);
const Component = connect(mapStateToProps, (dispatch) => ({ dispatch }))(MainBody);
-
export default reduxLoadSubApp({
name: "MainBody",
Component,
useReactRouter: true,
- reduxEnhancer: () => applyMiddleware(logger),
+ middleware: () => [logger],
+ reduxShareStore: true,
+ reduxReducers: reducers,
StartComponent: (props) => {
return (
@@ -76,7 +75,4 @@ export default reduxLoadSubApp({
);
},
- prepare: async () => {},
- reduxShareStore: true,
- reduxReducers,
});
diff --git a/samples/poc-subapp-redux/src/04.footer/subapp-footer.jsx b/samples/poc-subapp-redux/src/04.footer/subapp-footer.jsx
index 014abab9c..7ddf26b6f 100644
--- a/samples/poc-subapp-redux/src/04.footer/subapp-footer.jsx
+++ b/samples/poc-subapp-redux/src/04.footer/subapp-footer.jsx
@@ -13,14 +13,13 @@ const email = (email = "", action = {}) => {
const setEmail = (value) => {
return {
type: "EMAIL",
- payload: value
+ payload: value,
};
};
-const reducers = {email};
-
-const Footer = props => {
+const reducers = { email };
+const Footer = (props) => {
const onSubmit = () => {
const email = document.getElementById("email").value;
props.dispatch(setEmail(email));
@@ -31,7 +30,13 @@ const Footer = props => {
Redux state change demo in a subApp
Footer is a subApp. Click "Submit" to see Redux state change in browser console.
-
+
Submit
@@ -40,12 +45,12 @@ const Footer = props => {
};
Footer.propTypes = {
- title: PropTypes.string
+ title: PropTypes.string,
};
const Component = connect(
- state => state,
- dispatch => ({ dispatch })
+ (state) => state,
+ (dispatch) => ({ dispatch })
)(Footer);
export default reduxLoadSubApp({
@@ -54,12 +59,12 @@ export default reduxLoadSubApp({
reduxShareStore: true,
reduxReducers: reducers,
prepare: () => {
- return new Promise(resolve => {
+ return new Promise((resolve) => {
setTimeout(() => {
resolve({
- title: "Online Store Copyright"
+ title: "Online Store Copyright",
});
}, 2000);
});
- }
+ },
});
diff --git a/samples/poc-subapp-redux/src/redux-store/actions/number-actions.js b/samples/poc-subapp-redux/src/redux-store/actions/number-actions.js
new file mode 100644
index 000000000..596d610cc
--- /dev/null
+++ b/samples/poc-subapp-redux/src/redux-store/actions/number-actions.js
@@ -0,0 +1,8 @@
+import { createAction } from "@reduxjs/toolkit";
+
+export const ACTION_CONSTANT = {
+ INCREASE: "number/increase",
+ DECREASE: "number/decrease",
+};
+export const incNumber = createAction(ACTION_CONSTANT.INCREASE);
+export const decNumber = createAction(ACTION_CONSTANT.DECREASE);
diff --git a/samples/poc-subapp-redux/src/redux-store/reducers/number-reducer.js b/samples/poc-subapp-redux/src/redux-store/reducers/number-reducer.js
new file mode 100644
index 000000000..c50d68cc1
--- /dev/null
+++ b/samples/poc-subapp-redux/src/redux-store/reducers/number-reducer.js
@@ -0,0 +1,15 @@
+import { createReducer } from "@reduxjs/toolkit";
+import { incNumber, decNumber } from "../actions/number-actions";
+
+const initialState = { number: 1000 };
+
+export const numberReducer = createReducer(initialState, (builder) => {
+ builder
+ // eslint-disable-next-line consistent-return
+ .addCase(incNumber, (state, action) => {
+ state.number += 1;
+ })
+ .addCase(decNumber, (state, action) => {
+ state.number -= 1;
+ });
+});
diff --git a/samples/poc-subapp-redux/src/redux-store/reducers/root-reducer.js b/samples/poc-subapp-redux/src/redux-store/reducers/root-reducer.js
new file mode 100644
index 000000000..1660182f4
--- /dev/null
+++ b/samples/poc-subapp-redux/src/redux-store/reducers/root-reducer.js
@@ -0,0 +1,5 @@
+import { numberReducer } from "./number-reducer";
+
+export const reducers = {
+ numberReducer,
+};
diff --git a/samples/poc-subapp-redux/src/server-routes/default/index.js b/samples/poc-subapp-redux/src/server-routes/default/index.js
index a4c90130b..1c21abf85 100644
--- a/samples/poc-subapp-redux/src/server-routes/default/index.js
+++ b/samples/poc-subapp-redux/src/server-routes/default/index.js
@@ -93,7 +93,7 @@ const Template = (
/>
-