Child Applications are re-rendering and the states are getting reset when the apllications are loaded using the concept of Dynamic Remote Containers
Hi,
I have developed a microfrontend application where the parent application loads all the child applications using the concept of webpack Dynamic Remote Containers. Currently I have a problem when the parent component's state is updated, the child application is also re-rendered and the child application's state is also reset.
I use the Okta React SecureRoute to route to the child application as it is required for user authentication. Every hour the Okta access token is updated and in this case the Okta SecureRoute component is re-rendered. In this case, the child application will also be re-rendered and the state will be reset. Because of this state reset, we are not able to use the child application.
The state of the child application is reset only when the application is loaded as a dynamic remote container. Application state reset does not occur when normal React component is loaded via Okta React SecureRoute.
I kindly request you to help in resolving this app reset issue.
Attaching the link of okta-react implementation code for reference https://www.npmjs.com/package/@okta/okta-react
The sample code can be found below.
In the below code System componet loads the child application as dynamic remote containers.
App.js
const appConfig = {
url: 'http://localhost:4000/remoteEntry.js',
scope: 'app1',
module: './App'
};
<Security oktaAuth={oktaAuth}>
<Switch>
<Route exact path="/" render={() => <Home />} />
<Route path="/login/callback" component={CustomLoginCallback} />
<Route path="/error" component={CustomLoginCallback} />
<SecureRoute
path="/:id"
render={() => (
<React.Suspense fallback={<Loader />}>
<System system={appConfig} oktaAuth={oktaAuth} />
</React.Suspense>
)}
/>
</Switch>
</Security>
System.js
import React from 'react';
import Loader from '../Loader/Loader';
import ErrorBoundary from '../ErrorBoundary';
import Feedback from '../Feedback/Feedback';
//Dynamic loading of react apps
function loadComponent(scope, module) {
return async () => {
// Initializes the share scope. This fills it with known provided modules from this build and all remotes
await __webpack_init_sharing__('default');
const container = window[ scope ]; // or get the container somewhere else
// Initialize the container, it may provide shared modules
await container.init(__webpack_share_scopes__.default);
const factory = await window[ scope ].get(module);
const Module = factory();
return Module;
};
}
const useDynamicScript = (args) => {
const [ ready, setReady ] = React.useState(false);
const [ failed, setFailed ] = React.useState(false);
React.useEffect(() => {
if (!args.url) {
return;
}
const element = document.createElement('script');
element.src = args.url;
element.type = 'text/javascript';
element.async = true;
setReady(false);
setFailed(false);
element.onload = () => {
console.log(`Dynamic Script Loaded: ${ args.url }`);
setReady(true);
};
element.onerror = () => {
console.error(`Dynamic Script Error: ${ args.url }`);
setReady(true);
setFailed(true);
};
document.head.appendChild(element);
return () => {
console.log(`Dynamic Script Removed: ${ args.url }`);
document.head.removeChild(element);
};
}, [ args.url ]);
return {
ready,
failed,
};
};
const System = (props) => {
const { ready, failed } = useDynamicScript({
url: props.system && props.system.url,
});
if (!props.system) {
return <Feedback message="Error! Not a system specified URL" />;
}
if (!ready) {
return <Loader />;
//return <h2>Loading dynamic script: {props.system.url}</h2>;
}
if (failed) {
return <h4>Failed to load dynamic script: {props.system.url}</h4>;
}
const Component = React.lazy(
loadComponent(props.system.scope, props.system.module)
);
return (
<React.Suspense fallback={ <Loader /> }>
<ErrorBoundary>
<Component { ...props } />
</ErrorBoundary>
</React.Suspense>
);
};
export default System;
Please help!