'Redux state change not reflected when connecting multiple React modules to same store
I am working on a React application (not CRA template) which consists multiple modules and I am trying to connect some of the modules to same Redux store so that they can share the same state and actions, e.g. Module A and B are connecting to same store, and whenever Module A dispatch state change, Module B should react to it.
However I notice Module B seems not to be receiving the state change triggered by Module A even though Redux Devtools did show a state changed from Module A. Below is my code and screenshot of Redux and React Devtools.
Module A
import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";
import { useDispatch } from "react-redux";
import { setVisibility } from "../../commonComponents/PageLoadingAnimation/reduxSlice";
// import { setActionsDialog } from "../../commonComponents/ActionsDialog/reduxSlice";
import { iso31661 } from "iso-3166";
import { allCountries } from "country-telephone-data";
import _ from "lodash";
import { Provider } from "react-redux";
import store from "../../store";
// Sort iso-3166 country list alphabetically based on its names
const sortedCountryList = iso31661?.sort((a, b) => a.name.localeCompare(b.name));
const BuyerRegister = () => {
/*** 1 ***/ const [birthDate, setBirthDate] = useState();
/*** 2 ***/ const [countrySelection, setCountrySelection] = useState(sortedCountryList[0]?.alpha2); // Set first country as default value
/*** 3 ***/ const [codeSelection, setCodeSelection] = useState(`${allCountries?.[0]?.iso2?.toUpperCase()}(${allCountries?.[0]?.dialCode})`);
/*** 4 ***/ const [phoneNumber, setPhoneNumber] = useState("");
/*** 5 ***/ const [formErrors, setFormErrors] = useState({});
const dispatch = useDispatch();
useEffect(() => {
dispatch(setVisibility(true));
}, []);
return (
<>
Buyer Register page
</>
)
}
ReactDOM.render(
(
<React.StrictMode>
<Provider store={store}>
<BuyerRegister />
</Provider>
</React.StrictMode>
),
document.getElementById("root")
);
Module B
import React, { useEffect } from "react"
import ReactDOM from "react-dom";
import { Provider, useSelector } from "react-redux";
import store from "../../store";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faSpinner } from "@fortawesome/free-solid-svg-icons";
import { Box } from "@mui/material";
import classes from "./styles.scss";
import styles from "./styles";
const PageLoadingAnimation = () => {
const { isVisible } = useSelector(state => state.pageLoadingAnimation);
useEffect(() => {
console.log("is visible udpated: ", isVisible);
}, [isVisible]);
return (
<>
{
isVisible ? (
<Box component="div" sx={styles.animationWrapper}>
<Box component="div" sx={styles.iconWrapper}>
<FontAwesomeIcon icon={faSpinner} className={classes["spinner-icon"]} size="3x" />
</Box>
<Box component="div">
Loading
<Box component="span" className={classes["first-dot"]}>.</Box>
<Box component="span" className={classes["second-dot"]}>.</Box>
<Box component="span" className={classes["third-dot"]}>.</Box>
</Box>
</Box>
) : null
}
</>
);
}
ReactDOM.render(
(
<React.StrictMode>
<Provider store={store}>
<PageLoadingAnimation />
</Provider>
</React.StrictMode>
),
document.getElementById("page-loading-animation")
);
Redux store
import { configureStore } from "@reduxjs/toolkit";
import pageLoadingAnimationReducer from "../commonComponents/PageLoadingAnimation/reduxSlice";
// import actionsDialogReducer from "../commonComponents/ActionsDialog/reduxSlice";
export default configureStore({
reducer: {
pageLoadingAnimation: pageLoadingAnimationReducer,
// actionsDialog: actionsDialogReducer
}
});
Webpack configuration
const path = require("path");
const webpack = require("webpack");
const dotenv = require("dotenv");
var config = {
cache: false,
entry: {
bodyHeader: ["babel-polyfill", path.resolve("./src/commonComponents/BodyHeader/index")],
bodyFooter: [path.resolve("./src/commonComponents/BodyFooter/index")],
pageLoadingAnimation: [path.resolve("./src/commonComponents/PageLoadingAnimation/index")],
// actionsDialog: [path.resolve("./src/commonComponents/ActionsDialog/index")],
buyerLogin: [path.resolve("./src/pages/BuyerLogin/index")],
buyerRegister: [path.resolve("./src/pages/BuyerRegister/index")]
},
output: {
filename: "[name].bundled.js",
path: path.join(__dirname, "/build")
},
module: {
rules: [
{
loader: "babel-loader",
test: /\.js$/,
exclude: /node_modules/
},
{
test: /\.s[ac]ss$/i,
use: [
"style-loader", // Inject CSS into DOM
{
// Resolve syntax "@import" and "url()" into JS readable "import / require()"
loader: "css-loader",
options: {
modules: {
localIdentName: "[local]--[hash:base64:7]"
}
}
},
"sass-loader", // Loads SASS / SCSS file and compile it to CSS
]
},
{
test: /\.css$/i,
use: [
"style-loader",
"css-loader"
]
}
]
},
plugins: [
new webpack.DefinePlugin({
"process.env": JSON.stringify(dotenv.config().parsed)
})
]
}
module.exports = (env, arg) => {
if(arg.mode === "development"){
config.devtool = "source-map";
config.watch = true; // To enable hot reload whenever file changes
config.watchOptions = {
aggregateTimeout: 300 // To add delay before rebuilding once first file changed, to
// aggregate any other changes made during this time period into
// one rebuild
}
}
config.mode = arg.mode || "development";
return config;
}
ExpressJS view template
doctype html
html
head
title Genuine Ecomm
style.
body {
margin: 0px;
}
body
//------------ Module B ------------//
include pageLoadingAnimation.pug
include bodyHeader.pug
//------------ Module A and its bundled JS is inside this block ------------//
block content
include bodyFooter.pug
block scripts
//------------ Module B's bundled JS file ------------//
script(src="/pageLoadingAnimation.bundled.js")
script(src="/bodyHeader.bundled.js")
script(src="/bodyFooter.bundled.js")
Redux Devtools when Module A dispatch state change
Module B useSelector state status
My objective is to make Module B (this is a loading animation) as a common component which can be used by different modules (like Module A) and to have a consistence and easy way to update Module B's state when necessary. Also try to avoid every module to have to import Module B explicitly. Thank you.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|