NGRX effect stale R3Injector after destroying and reinitialising module

1k views Asked by At

I am attempting to use module federation along with ngrx store & ngrx effects in my webapp which is all in working order for the most part. However, I wish to destroy my NgModuleRef when switching to another lazy loaded route. Hence if I have one module called MyAccountModule at /myaccount and another module called Dashboard at /dashboard then I wish to destroy the MyAccountModule when switching to the /dashboard route and destroy the /dashboard route when switching back to /myaccount.

I have achieved this using this code:

export class MyAccountModule implements OnDestroy {
  private destroyed$ = new Subject<boolean>();

  constructor(
    private router: Router, 
    private currentNgModuleRef: NgModuleRef<MyAccountModule>,
    private store: Store<AppState>,
    private webSocket: WebsocketService
  ) {

    this.store.dispatch(new InitializeMyAccountModuleAction());
    this.router.events
      .pipe(
        filter((event) => event instanceof NavigationEnd),
        takeUntil(this.destroyed$),
        map(event=> event as RouterEvent)
      )
      .subscribe(($evt)=>{
        if (!$evt.url.includes('myaccount')){
           this.currentNgModuleRef.destroy();
        }
      });
    
  }


  ngOnDestroy() {

    this.store.removeReducer('manageAccountState');
    
    if (this.webSocket.sockets.has(environment.wsURL)) this.store.dispatch(new WebsocketDisconnectAction({ wsURL: environment.wsURL }));

    this.destroyed$.next(true);
    this.destroyed$.complete();
  }

This works fine and both routes seem to display & function correctly. However, if you were to route from /myaccount to /dashboard & then back to /myaccount for example. It seems upon the reinitialising of MyAccountModule (/myaccount), it does not appear to reinstantiate EffectsModule.forFeature(). Meaning that when I trigger an ngrx effect it uses the original R3Injector therefore when calling a service within the effect such as a http service it lacks the relevant providers because the instance of the injector is that of the initially loaded module which is now in a destroyed state. Meaning for some reason or another ngrx does not seem to update the state surrounding the running of the contents of createEffect(()=> to utilise the newest instance of R3Injector.

Therefore I guess my question becomes is there a way to manually destroy EffectsModule.forFeature() from memory? If not, is it possible to de-register the effect? Or some way of re-initialising the injector instance provider for the module within the constructor.

The error received is due to it being thrown in core.js:

assertNotDestroyed() {
        if (this._destroyed) {
            throw new Error('Injector has already been destroyed.');
        }
}

where this = R3Injector and the value of R3Injector properties includes _destroyed:true due to it being the previous instance.

Thanks in advance for any assistance.

0

There are 0 answers