angular-redux / store

Angular 2+ bindings for Redux
MIT License
1.34k stars 202 forks source link

"NullInjectorError: No provider for NgZone" after upgrade to Angular 6 and angular-redux/store 9 #548

Closed AntJanus closed 3 years ago

AntJanus commented 5 years ago

This is a...

What toolchain are you using for transpilation/bundling?

Environment

NodeJS Version: 8.11.4 Typescript Version: 3.01 Angular Version: 6.1.10 @angular-redux/store version: 9.0.0 @angular/cli version: (if applicable) OS: Windows

Expected Behaviour:

NgRedux to load via dependency injection.

Actual Behaviour:

Application fails to load due to dependency injection issues. zone.js is at 0.8.26 version and RxJS is at 6.3.3 with a compat layer.

Stack Trace/Error Message:

Unhandled Promise rejection: StaticInjectorError(Gen2AppModule)[NgRedux -> NgZone]: 
  StaticInjectorError(Platform: core)[NgRedux -> NgZone]: 
    NullInjectorError: No provider for NgZone! ; Zone: <root> ; Task: Promise.then ; Value: Error: "StaticInjectorError(Gen2AppModule)[NgRedux -> NgZone]: 
  StaticInjectorError(Platform: core)[NgRedux -> NgZone]: 
    NullInjectorError: No provider for NgZone!"

Additional Notes:

Here's my application bootstrap (summarized to remove proprietary code):

import './vendor';
import Ng1App from '../app/app';
import * as angular from 'angular';
import 'zone.js';
import { NgModule, enableProdMode, forwardRef } from '@angular/core';
import { store } from '../reduxStore';
import { BrowserModule } from '@angular/platform-browser';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { UpgradeModule } from '@angular/upgrade/static';
import { RouterModule, UrlHandlingStrategy } from '@angular/router';
import {
  HashLocationStrategy,
  LocationStrategy,
  APP_BASE_HREF,
} from '@angular/common';
import { Store } from 'redux';
import { NgReduxModule, NgRedux } from '@angular-redux/store';

import { IAppState } from '../reducers/IAppState';
import { AppRootComponent } from './pages/AppRootComponent';

@NgModule({
  declarations: [AppRootComponent],
  entryComponents: [],
  imports: [
    UpgradeModule,
    NgReduxModule,
  ],
  providers: [
    { provide: LocationStrategy, useClass: HashLocationStrategy },
    { provide: APP_BASE_HREF, useValue: '!' },
  ],
  bootstrap: [AppRootComponent],
})
class Gen2AppModule {
  constructor(private upgrade: UpgradeModule, ngRedux: NgRedux<IAppState>) {
    ngRedux.provideStore(store as Store<IAppState>);
  }

  ngDoBootstrap() {}
}

const upgradedModules = [];

    angular.element(document).ready(function() {
      platformBrowserDynamic()
        .bootstrapModule(Gen2AppModule)
        .then(platformRef => {
          const injector = platformRef.injector;
          const upgrade = injector.get(UpgradeModule) as UpgradeModule;
          upgrade.bootstrap(document.body, [Ng1App.name, ...upgradedModules]);
        });
    });
AntJanus commented 5 years ago

A quick update, providing NgReduxModule manually seems to fix this problem via:

providers: [
 // ... other providers
{ provide: NgRedux, useFactory: _ngReduxFactory, deps: [NgZone]}
],

I imported _ngReduxFactory (VS Code figured out the location automatically) via:

import { NgZone } from '@angular/core';
import { _ngReduxFactory } from '@angular-redux/store/lib/src/ng-redux.module';
AntJanus commented 5 years ago

Hmm, I wonder if my webpack setup bundles things in a weird way before zone.js gets loaded.