I have currently a host - container and a remote - dashboard.
I have a full blown redux+saga setup at my container, which I am exposing to remote using Module federation as well.
plugins: [
new ModuleFederationPlugin({
name: "container",
filename: "remoteEntry.js",
remotes: {
dashboard: "dashboard@http://localhost:8081/remoteEntry.js",
},
exposes: {
'./GlobalStore': './src/redux/index.js'
},
shared: {
...dependencies,
...Object.fromEntries(
singletonDependencies.map(dep => [
dep,
{
singleton: true,
requiredVersion: dependencies[dep],
}
])
)
},
})
]
Now my requirement is to have the dashboard manage it's own particular states, inside the dashboard, I am checking whether the app is running inside the container or not. If it is running standalone I am doing this full-blown redux+saga setup inside there as well (as if it's running individually without knowing there's a container app).
If it's running inside the container, I am using this
import React from 'react';
import { Provider } from "react-redux";
import GlobalStore from 'container/GlobalStore';
import { RouterProvider } from 'react-router';
const InsideContainerApp = ({ router }) => {
return (
<Provider store={GlobalStore}>
<RouterProvider router={router} />
</Provider>
);
}
export default InsideContainerApp;
The imported store from the container.
Anyone knows how can I inject my reducers and sagas from the remote to the host in run-time or is it even required to do this way? My ask is that I don't want to define all the slices / reducers in the container and I want my remotes to have full autonomy how they want to define their state structures.
I have currently a host - container and a remote - dashboard.
I have a full blown redux+saga setup at my container, which I am exposing to remote using Module federation as well.
plugins: [
new ModuleFederationPlugin({
name: "container",
filename: "remoteEntry.js",
remotes: {
dashboard: "dashboard@http://localhost:8081/remoteEntry.js",
},
exposes: {
'./GlobalStore': './src/redux/index.js'
},
shared: {
...dependencies,
...Object.fromEntries(
singletonDependencies.map(dep => [
dep,
{
singleton: true,
requiredVersion: dependencies[dep],
}
])
)
},
})
]
Now my requirement is to have the dashboard manage it's own particular states, inside the dashboard, I am checking whether the app is running inside the container or not. If it is running standalone I am doing this full-blown redux+saga setup inside there as well (as if it's running individually without knowing there's a container app).
If it's running inside the container, I am using this
import React from 'react';
import { Provider } from "react-redux";
import GlobalStore from 'container/GlobalStore';
import { RouterProvider } from 'react-router';
const InsideContainerApp = ({ router }) => {
return (
<Provider store={GlobalStore}>
<RouterProvider router={router} />
</Provider>
);
}
export default InsideContainerApp;
The imported store from the container.
Anyone knows how can I inject my reducers and sagas from the remote to the host in run-time or is it even required to do this way? My ask is that I don't want to define all the slices / reducers in the container and I want my remotes to have full autonomy how they want to define their state structures.
Share Improve this question asked Mar 22 at 13:27 Devansh NigamDevansh Nigam 5571 gold badge6 silver badges8 bronze badges1 Answer
Reset to default 0I had a project with very similar requirements. Generally speaking You don't need to define all slices/reducers upfront in the container. You can use dynamic reducer injection and saga middleware injection (You can search plenty of resources about it)
I would configure the store to support dynamic reducers and saga injections and expose the helper functions, that way the remote can call those helpers when they mount.
Heres a relevant snippet
// Dynamic reducer injection
export const injectReducer = (key, reducer) => { if (!store.asyncReducers[key]) {
store.asyncReducers[key] = reducer;
store.replaceReducer({
...staticReducers,
...store.asyncReducers,
}); } };
// Dynamic saga injection
export const injectSaga = (key, saga) => { if (!store.runningSagas.has(key)) {
sagaMiddleware.run(saga);
store.runningSagas.add(key); } };
after you expose then they can be used like this :
useEffect(() => {
injectReducer('dashboard', myReducer);
injectSaga('dashboard', mySaga);
}, []);
Haven't tried it, But it believe you can just create a component such as
const StoreInjector = ({ reducer, saga, reducerKey }) => {
useEffect(() => {
injectReducer(reducerKey, reducer);
injectSaga(reducerKey, saga);
}, []);
return null;
};
and just call it in the top of your remote.