Is it possible to share NGXS store between separate Angular (sub)projects?
Asked Answered
D

1

9

The situation: I have a micro-frontend made of a host Angular app and many Angular libraries imported as modules containing components that behave as 'sub-apps'.

The goal: I want to share the NGXS store created in the host app between all sub-apps, so that each sub-app has its own slice of the global state and it can access the global state as well.

In the host app I am creating the state as follows:

@State<ApplicationStateModel>({
  name: 'host',
  defaults: {
    context: {
      language: 'en'
    },
    apps: {}
  }
})
export class ApplicationState {...}

and in the sub-apps I want to be able to send actions as well as to slice this state, something like:

constructor(private store: Store) {
   // slice the context
   this.context$ = this.store.select(state => state.host.context);
   // slice this sub-app state
   this.state$ = this.store.select(state => state.host.apps['myapp']);
}

...

// dispatch an action
this.store.dispatch(new UpdateContext());

The problem: how can I pass the store from the host app to the sub-apps? I am guessing there might be a way to do this by using the .forRoot() or .forFeature() functions of the module during import.. but I am totally lost.

Dilantin answered 15/3, 2019 at 13:46 Comment(6)
Are you lazy loading your sub-apps?Fisher
@Fisher currently not, just importing the modules in the host app.module.tsDilantin
look at this example I made: stackblitz.com/edit/ngxs-todos-mki5w1?file=src/app/… The folder called "test-app" is a module. you can think of it as a sub app. I didnt have to do anything special to get the store hooked up. I am displaying the todo list in two different components both subscribed to the store.Fisher
@Fisher that is just a separate module, it is not the same as having a separate project.. in a separate project you would need to do NgxsModule.forRoot(..) (or something similar) to get the store working, while in your example you don't. It has to work with import {TestAppModule} from '@myscope/test-app';Dilantin
Im using ngrx and have separate apps via scoped npm packages locally. I know ngrx and ngxs arent 100% the same but the concepts should be. We lazy load our sub apps(npm packages) and instantiated them as feature stores: ngxs.gitbook.io/ngxs/advanced/lazyFisher
also trying to use ngxs with micro front ends. I am using single-spa.Alguire
A
1

You might be able to use the store.snapshot() and store.reset() methods to do that.

Let's assume your state models match across your apps... Your master app holds a valid store --> the master app calls store.snapshot(), serializes the snapshot object and propagates it to your sub-app (using websockets, long polling, or what have you) --> your sub-app, on receiving the serialized snapshot, deserializes it and calls store.reset(), passing in the snapshot object.

This does not ensure the stores will be synchronized, though. Modifying the state in a sub-app will modify the state only there. You can reverse the snapshot pass to propagate the state back. As you can see, this can get messy quite quickly...

A better approach would be to use some kind of front-to-back-end event mechanism to propagate NGXS action dispatches to clients that subscribe to it. For .NET, for example, you can use SignalR (https://dotnet.microsoft.com/apps/aspnet/real-time). There are other implementations for other stacks as well.

Hope this helps a little :-)

Accommodative answered 20/3, 2019 at 14:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.