Module federation re-renders many times a component in remote react app

Viewed 357

I'd like to render my RemoteApp into my ShellApp. My RemoteApp has got a useEffect which makes an API call, but it seems is executed a lot of times. So I suppose my remote component is re rendered more than it should be.

These are my webpack.config for ShellApp and RemoteApp:

Remote app

const webpack = require('webpack');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const ESLintPlugin = require('eslint-webpack-plugin');

const deps = require('./package.json').dependencies;

module.exports = {
  output: {
    publicPath: 'http://localhost:3003/',
  },

  resolve: {
    extensions: ['.tsx', '.ts', '.jsx', '.js', '.json', '*'],
  },

  devServer: {
    port: 3003,
    historyApiFallback: true,
    hot: true,
  },

  module: {
    rules: [
      {
        test: /\.m?js/,
        type: 'javascript/auto',
        resolve: {
          fullySpecified: false,
        },
      },
      {
        test: /\.css$/i,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              modules: true,
            },
          },
        ],
      },
      {
        test: /\.(ts|tsx|js|jsx)$/,
        exclude: /node_modules/,
        use: ['babel-loader'],
      },
      {
        test: /\.svg$/,
        use: ['@svgr/webpack'],
      },
      {
        test: /\.json$/,
        loader: 'json-loader',
      },
    ],
  },

  plugins: [
    new ModuleFederationPlugin({
      name: 'remoteApp',
      filename: 'remoteEntry.js',
      remotes: {},
      exposes: {
        './Dashboard': './src/pages/Dashboard/Dashboard.jsx',
      },
      shared: {
        ...deps,
        react: {
          singleton: true,
          requiredVersion: deps.react,
        },
        'react-dom': {
          singleton: true,
          requiredVersion: deps['react-dom'],
        },
      },
    }),
    new HtmlWebPackPlugin({
      template: './public/index.html',
    }),
    new webpack.HotModuleReplacementPlugin(),
    new ESLintPlugin({
      extensions: ['js', 'jsx'],
    }),
  ],
};

Shell app

const webpack = require('webpack');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const ESLintPlugin = require('eslint-webpack-plugin');

const deps = require('./package.json').dependencies;

module.exports = {
  output: {
    publicPath: 'http://localhost:3000/',
  },

  resolve: {
    extensions: ['.tsx', '.ts', '.jsx', '.js', '.json', '*'],
  },

  devServer: {
    port: 3000,
    historyApiFallback: true,
    hot: true,
  },

  module: {
    rules: [
      {
        test: /\.m?js/,
        type: 'javascript/auto',
        resolve: {
          fullySpecified: false,
        },
      },
      {
        test: /\.css$/i,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              modules: true,
            },
          },
        ],
      },
      {
        test: /\.(ts|tsx|js|jsx)$/,
        exclude: /node_modules/,
        use: ['babel-loader'],
      },
      {
        test: /\.svg$/,
        use: ['@svgr/webpack'],
      },
      {
        test: /\.json$/,
        loader: 'json-loader',
      },
    ],
  },

  plugins: [
    new ModuleFederationPlugin({
      name: 'frontend_shell',
      filename: 'remoteEntry.js',
      remotes: {
        dashboard: 'frontend_equity_credit@http://localhost:3003/remoteEntry.js',
      },
      exposes: {},
      shared: {
        ...deps,
        react: {
          singleton: true,
          requiredVersion: deps.react,
        },
        'react-dom': {
          singleton: true,
          requiredVersion: deps['react-dom'],
        },
      },
    }),
    new HtmlWebPackPlugin({
      template: './public/index.html',
    }),
    new webpack.HotModuleReplacementPlugin(),
    new ESLintPlugin({
      extensions: ['js', 'jsx'],
    }),
  ],
};

I'm importing the remote component like this in Shell App.jsx

import Dashboard from 'dashboard/Dashboard';

function App() {

  return (
    <div>
      <Dashboard/>
    </div>
  );
}

Finally, this is my Dashboard.jsx component inside the Remote application

import React, { useEffect } from 'react';
import { useStore } from './store/store';

function Dashboard() {
  const { globalStore, actions, dispatch } = useStore();
  const loggedUserId = globalStore.auth?.userInfo?.id;

  useEffect(() => {
    if (loggedUserId) {
      dispatch(actions.getUsersPreferences(loggedUserId)); //API CALL
    }
  }, [loggedUserId]);
  
  return (
    <>
      {/*render api response*/}
    </>
  );
}

export default Dashboard;

I got this in console:

Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

Any ideas?

0 Answers
Related