'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 enter image description here

Module B useSelector state status enter image description here

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