[ ] Regression (a behavior that used to work and stopped working in a new release)
[X] Bug report
[ ] Feature request
[ ] Documentation issue or request
Hello ,sorry for my bad English
When I compile my application in -AOT, the Angular console does not send me an error (compilation is good). But in my browser, I have this error "auth.effects.ts: 81 Uncaught TypeError: Can not read property 'ofType' of undefined"
I would like the error to disappear and the application will launch
I Have :
My Auth.effect.ts :
import { Injectable } from '@angular/core';
import { Headers } from '@angular/http';
// import @ngrx
import { Effect, Actions, ofType } from '@ngrx/effects';
import { toPayload } from '@ngrx/effects/@ngrx/effects';
import { Action } from '@ngrx/store';
import { FacebookService, InitParams, LoginResponse } from 'ngx-facebook';
// import rxjs
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/switchMap';
import * as sdk from '../../shared/sdk';
// import actions
import {
ActionTypes,
AuthenticatedErrorAction,
AuthenticatedSuccessAction,
SignInErrorAction,
SignInSuccessAction,
SignOutErrorAction,
SignOutSuccessAction,
RegisterErrorAction,
RegisterSuccessAction,
SignInAction,
RequestResetPasswordAction,
RequestResetPasswordErrorAction,
RequestResetPasswordSuccessAction,
SetNewPasswordAction,
SetNewPasswordErrorAction,
SetNewPasswordSuccessAction,
GetCurrentUserAction,
GetCurrentUserErrorAction,
GetCurrentUserSuccessAction,
FacebookLoginSuccessAction,
FacebookLogoutAction,
FacebookLoginErrorAction,
LoginNetEntrepriseSuccessAction,
LoginNetEntrepriseErrorAction,
FacebookLogoutSuccessAction,
FacebookLogoutErrorAction,
VerifiyEmailSuccessAction,
VerifiyEmailErrorAction,
SendVerifiyEmailSuccessAction,
SendVerifiyEmailErrorAction,
DeleteAccountAction,
DeleteAccountErrorAction,
DeleteAccountSuccessAction
} from './auth.actions';
/**
* Effects offer a way to isolate and easily test side-effects within your
* application.
* The `toPayload` helper function returns just
* the payload of the currently dispatched action, useful in
* instances where the current state is not necessary.
*
* Documentation on `toPayload` can be found here:
* https://github.com/ngrx/effects/blob/master/docs/api.md#topayload
*
* If you are unfamiliar with the operators being used in these examples, please
* check out the sources below:
*
* Official Docs: http://reactivex.io/rxjs/manual/overview.html#categories-of-operators
* RxJS 5 Operators By Example: https://gist.github.com/btroncone/d6cf141d6f2c00dc6b35
*/
@Injectable()
export class AuthEffects {
/**
* Authenticate user.
*/
@Effect()
public signIn: Observable<Action> = this.actions
.ofType(ActionTypes.SIGN_IN)
.debounceTime(500)
.map((action: SignInAction) => action.payload)
.switchMap((payload: any) => {
return this.userService
.login({
email: payload.email,
password: payload.password
})
.map(user => new SignInSuccessAction({ user: user }))
.catch(error => Observable.of(new SignInErrorAction({ error: error })));
});
/**
...
apply() { }
/**
* @constructor
* @param {Actions} actions
* @param {UserService} userService
*/
constructor(
private actions: Actions,
private userService: sdk.CustomUserApi,
private authService: sdk.LoopBackAuth,
private _fb: FacebookService
) { }
}
my auth.action.ts :
// import @ngrx
import { Action } from '@ngrx/store';
// import type function
import { type } from '../../shared/util';
import * as sdk from '../../shared/sdk';
import * as shared from '../../shared';
export const ActionTypes = {
CLEAR_AUTH: type('[auth] Clear auth'),
SIGN_IN: type('[auth] Sign in'),
SIGN_IN_ERROR: type('[auth] Sign in error'),
SIGN_IN_SUCCESS: type('[auth] Sign in success'),
AUTHENTICATED: type('[auth] Authenticated'),
AUTHENTICATED_ERROR: type('[auth] Authenticated error'),
AUTHENTICATED_SUCCESS: type('[auth] Authenticated success'),
SIGN_OUT: type('[auth] Sign off'),
SIGN_OUT_ERROR: type('[auth] Sign off error'),
SIGN_OUT_SUCCESS: type('[auth] Sign off success'),
REGISTER: type('[auth] Register'),
REGISTER_ERROR: type('[auth] Register error'),
REGISTER_SUCCESS: type('[auth] Register success'),
REQUEST_RESET_PASSWORD: type('[auth] Request reset password'),
REQUEST_RESET_PASSWORD_ERROR: type('[auth] Request reset password error'),
REQUEST_RESET_PASSWORD_SUCCESS: type('[auth] Request reset password success'),
SET_NEW_PASSWORD: type('[auth] Set new password'),
SET_NEW_PASSWORD_SUCCESS: type('[auth] Set new password success'),
SET_NEW_PASSWORD_ERROR: type('[auth] Set new password error'),
GET_USER: type('[auth] Get current user'),
GET_USER_SUCCESS: type('[auth] Get current user success'),
GET_USER_ERROR: type('[auth] Get current user error'),
FACEBOOK_LOGIN: type('[auth] Facebook login'),
FACEBOOK_LOGIN_SUCCESS: type('[auth] Facebook login success'),
FACEBOOK_LOGIN_ERROR: type('[auth] Facebook login error'),
FACEBOOK_LOGOUT: type('[auth] Facebook logout'),
FACEBOOK_LOGOUT_SUCCESS: type('[auth] Facebook logout success'),
FACEBOOK_LOGOUT_ERROR: type('[auth] Facebook logout error'),
LOGIN_NET_ENTREPRISE: type('[auth] Net entreprise login'),
LOGIN_NET_ENTREPRISE_SUCCESS: type('[auth] Net entreprise login success'),
LOGIN_NET_ENTREPRISE_ERROR: type('[auth] Net entreprise login error'),
VERIFY_EMAIL: type('[auth] Verify user email'),
VERIFY_EMAIL_SUCCESS: type('[auth] Verify user email success'),
VERIFY_EMAIL_ERROR: type('[auth] Verify user email error'),
SEND_VERIFY_EMAIL: type('[auth] Send verify user email'),
SEND_VERIFY_EMAIL_SUCCESS: type('[auth] Send verify user email success'),
SEND_VERIFY_EMAIL_ERROR: type('[auth] Send verify user email error'),
DELETE_ACCOUNT: type('[auth] delete account'),
DELETE_ACCOUNT_SUCCESS: type('[auth] delete account success'),
DELETE_ACCOUNT_ERROR: type('[auth] delete account error')
};
export interface Action {
type: string;
payload?: any;
}
/**
* Clear.
* @class ClearAction
* @implements {Action}
*/
export class ClearAction implements Action {
public type: string = ActionTypes.CLEAR_AUTH;
constructor(public payload?: any) { }
}
/**
* Sign in.
* @class SignInAction
* @implements {Action}
*/
export class SignInAction implements Action {
public type: string = ActionTypes.SIGN_IN;
constructor(public payload: { email: string, password: string }) { }
}
....
/**
* Actions type.
* @type {Actions}
*/
export type Actions =
SignInAction
| AuthenticatedAction
| AuthenticatedErrorAction
| AuthenticatedSuccessAction
| SignInErrorAction
| SignInSuccessAction
| RegisterAction
| RegisterErrorAction
| RequestResetPasswordAction
| RequestResetPasswordErrorAction
| RequestResetPasswordSuccessAction
| RegisterSuccessAction
| SetNewPasswordAction
| SetNewPasswordErrorAction
| SetNewPasswordSuccessAction
| GetCurrentUserAction
| GetCurrentUserErrorAction
| FacebookLoginAction
| FacebookLoginSuccessAction
| FacebookLoginErrorAction
| FacebookLogoutAction
| GetCurrentUserSuccessAction
| LoginNetEntrepriseAction
| LoginNetEntrepriseErrorAction
| LoginNetEntrepriseSuccessAction
| FacebookLogoutErrorAction
| FacebookLogoutSuccessAction
| VerifiyEmailErrorAction
| VerifiyEmailSuccessAction
| VerifyEmailAction
| SendVerifyEmailAction
| SendVerifiyEmailErrorAction
| SendVerifiyEmailSuccessAction
| DeleteAccountAction
| DeleteAccountErrorAction
| DeleteAccountSuccessAction
| ClearAction
;
my app.module.ts :
import { BrowserModule } from '@angular/platform-browser';
import {
NgModule,
TRANSLATIONS,
TRANSLATIONS_FORMAT,
LOCALE_ID,
APP_BOOTSTRAP_LISTENER,
InjectionToken,
Inject,
Type
} from '@angular/core';
import { FormsModule } from '@angular/forms';
import '../app/shared/rxjs-operators';
import { AppComponent } from './app.component';
// START STORE
import { StoreModule } from '@ngrx/store';
// import { reducers, State } from './app.reducers';
import * as core from './core';
import { StoreRouterConnectingModule } from '@ngrx/router-store';
import { EffectsModule, EffectSources } from '@ngrx/effects';
// END STORE
// START LOOPBACK SDK
import { SDKBrowserModule } from './shared/sdk';
// END LOOPBACK SDK
// START APPLICATION MODULES
import { AppRoutingModule } from './app-routing.module';
import { AuthModule } from './auth/auth.module';
import { FeaturesModule } from './features/features.module';
import { SharedModule } from './shared/shared.module';
import { LayoutModule } from './layout/layout.module';
import { AdminModule } from './admin/admin.module';
// END APPLICATION MODULES
// START ANGULAR MATERIAL MODULES
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
// END ANGULAR MATERIAL MODULES
import { PdfViewerModule } from 'ng2-pdf-viewer';
import { FacebookModule } from 'ngx-facebook';
import { DeviceDetectorModule } from 'ngx-device-detector';
// START DEV DEPENDENCIES
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
// END DEV DEPENDENCIES
// IMPORT TO FIX BUG DIALOG
import { AdressDialogComponent } from './shared/components';
// END IMPORT TO FIX BUG DIALOG
export const BOOTSTRAP_EFFECTS = new InjectionToken('Bootstrap Effects');
export function bootstrapEffects(effects: Type<any>[], sources: EffectSources) {
return () => {
effects.forEach(effect => sources.addEffects(effect));
};
}
export function createInstances(...instances: any[]) {
return instances;
}
export function provideBootstrapEffects(effects: Type<any>[]) {
return [
effects,
{ provide: BOOTSTRAP_EFFECTS, deps: effects, useFactory: createInstances },
{
provide: APP_BOOTSTRAP_LISTENER,
multi: true,
useFactory: bootstrapEffects,
deps: [[new Inject(BOOTSTRAP_EFFECTS)], EffectSources]
}
];
}
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
FormsModule,
AppRoutingModule,
AuthModule,
FeaturesModule,
SharedModule,
BrowserAnimationsModule,
SDKBrowserModule.forRoot(),
StoreModule.forRoot(core.reducers),
StoreRouterConnectingModule,
PdfViewerModule,
AdminModule,
FacebookModule.forRoot(),
DeviceDetectorModule.forRoot(),
// StoreDevtoolsModule.instrument({
// maxAge: 25 // Retains last 25 states
// }),
// EffectsModule.forRoot([core.router.effects.RouterEffects])
],
providers: [
{ provide: LOCALE_ID, useValue: 'fr-FR' },
core.reducerProvider,
provideBootstrapEffects([core.router.effects.RouterEffects])
],
entryComponents: [AdressDialogComponent], // SUITE BUG D'INGECTION DU CONTENU DANS LE DIALOG
bootstrap: [AppComponent]
})
export class AppModule { }
Browser: latest Google Chrome and Firefox (Mac)
"typescript": "2.4.2"
@angular/cli: "1.6.7",
"@angular/compiler-cli": "^5.2.9",
"@angular/language-service": "^5.2.9",
"ngrx-store-freeze": "^0.2.1",
"rxjs": "^5.5.8",
"ngrx-store-localstorage": "^0.2.4",
"ngrx-store-logger": "^0.2.1",
"ngx-device-detector": "^1.2.2",
"ngx-facebook": "^2.4.0",
"npm": "^5.8.0",
"@ngrx/core": "^1.2.0",
"@ngrx/effects": "^5.2.0",
"@ngrx/router-store": "^5.2.0",
"@ngrx/store": "^5.2.0",
"@ngrx/store-devtools": "^5.2.0",
if you need more information you can contact me with : [email protected]
Thanks
i think it's related to the pipeable-operators
https://github.com/ReactiveX/rxjs/blob/master/doc/pipeable-operators.md
you should stop using this kind of import:
import 'rxjs/add/operator/map';
to allow tree shaking basically use pipe. For your effects just try something like that:
import { ..., ofType } from '@ngrx/effects';
import { debounceTime, map, ... } from 'rxjs/operators';
...
this.actions.pipe(
ofType(ActionTypes.SIGN_IN),
debounceTime(500),
map((action: SignInAction) => action.payload),
...
comment:
import * as AllAuthActions from './auth.actions';
then you avoid to declare this huge list and you have autocomplete to access your actions
AllAuthActions.AuthenticatedErrorAction...
hope this help
I don't think this is an issue with ngrx itself. Please provide a reproduction of this issue with stackblitz or a repo.
I experienced the same issue when compiling a project with AOT:
core.js:1598 ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'pipe' of undefined
TypeError: Cannot read property 'pipe' of undefined
at new FileEffects (file.effects.ts:42)
at _createClass (core.js:9260)
at _createProviderInstance$1 (core.js:9234)
at initNgModule (core.js:9170)
at new NgModuleRef_ (core.js:9899)
at createNgModuleRef (core.js:9888)
at Object.debugCreateNgModuleRef [as createNgModuleRef] (core.js:11719)
at NgModuleFactory_.push.../../node_modules/@angular/core/fesm5/core.js.NgModuleFactory_.create (core.js:12421)
at MapSubscriber.project (router.js:3287)
at MapSubscriber.push.../../node_modules/rxjs/_esm5/internal/operators/map.js.MapSubscriber._next (map.js:75)
at new FileEffects (file.effects.ts:42)
at _createClass (core.js:9260)
at _createProviderInstance$1 (core.js:9234)
at initNgModule (core.js:9170)
at new NgModuleRef_ (core.js:9899)
at createNgModuleRef (core.js:9888)
at Object.debugCreateNgModuleRef [as createNgModuleRef] (core.js:11719)
at NgModuleFactory_.push.../../node_modules/@angular/core/fesm5/core.js.NgModuleFactory_.create (core.js:12421)
at MapSubscriber.project (router.js:3287)
at MapSubscriber.push.../../node_modules/rxjs/_esm5/internal/operators/map.js.MapSubscriber._next (map.js:75)
at resolvePromise (zone.js:814)
at resolvePromise (zone.js:771)
at zone.js:873
at ZoneDelegate.push.../../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
at Object.onInvokeTask (core.js:4053)
at ZoneDelegate.push.../../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:420)
at Zone.push.../../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:188)
at drainMicroTaskQueue (zone.js:595)
The problem has nothing to do with pipeable operators, but after some digging I found this issue and I can confirm that it has to to with barrel imports. If I reference my effects class from a barrel import...
EffectsModule.forFeature([fromStore.File.FileEffects])
...it will compile, but break with the above mentioned error in the browser. If I directly import the effects class and reference it that way...
EffectsModule.forFeature([FileEffects])
...everything works as expected.
It should be mentioned that this issue occurs only when compiling with AOT option and the module in question is a lazy-loaded module.
I got thinking, in the linked issue, I could see that the barrel re-exports sub-barrels, just like in my case, and creates intermediary module namespaces, like fromStore.File.FileEffects. So I tried what would happen, if I skip the inner namespace. So instead of:
...
import * as fromStore from './store';
@NgModule({
imports: [
CommonModule,
...
StoreModule.forFeature(fromStore.featureName, fromStore.reducers, { metaReducers: fromStore.metaReducers }),
EffectsModule.forFeature([fromStore.File.FileEffects]),
SomeRoutingModule
],...
})
export class SomeModule {}
... I would separately import the previously namespaced File barrel like this:
import * as fromStore from './store';
import * as fromFile from './store/file';
@NgModule({
imports: [
CommonModule,
...
StoreModule.forFeature(fromStore.featureName, fromStore.reducers, { metaReducers: fromStore.metaReducers }),
EffectsModule.forFeature([fromFile.FileEffects]),
SomeRoutingModule
],...
})
export class SomeModule {}
This actually works with AOT. So it looks like it's only a problem, for deeper nested re-exports. Maybe it helps to show my store barrel:
import { ActionReducerMap, MetaReducer } from '@ngrx/store';
import { environment } from '../../../environments/environment';
import * as fromFile from './file';
import { State } from './state';
export * from './state'
export const reducers: ActionReducerMap<State> = {
files: fromFile.reducer,
};
export const metaReducers: MetaReducer<State>[] = !environment.production ? [] : [];
export { fromFile as File };
Maybe the re-export is done incorrectly?
I am facing the same error:
Uncaught TypeError: Cannot read property 'ofType' of undefined
at new l (main.e7f84b40dc7ee41a9acb.js:1)
at main.e7f84b40dc7ee41a9acb.js:1
at Ii (main.e7f84b40dc7ee41a9acb.js:1)
at main.e7f84b40dc7ee41a9acb.js:1
at new l (main.e7f84b40dc7ee41a9acb.js:1)
at Object.eu [as createNgModuleRef] (main.e7f84b40dc7ee41a9acb.js:1)
at n.create (main.e7f84b40dc7ee41a9acb.js:1)
at main.e7f84b40dc7ee41a9acb.js:1
at t.invoke (polyfills.7da7c717970c702965aa.js:1)
at Object.onInvoke (main.e7f84b40dc7ee41a9acb.js:1)
does anyone has any clue?
alexanderwende solution worked for me
Most helpful comment
I experienced the same issue when compiling a project with AOT:
core.js:1598 ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'pipe' of undefined TypeError: Cannot read property 'pipe' of undefined at new FileEffects (file.effects.ts:42) at _createClass (core.js:9260) at _createProviderInstance$1 (core.js:9234) at initNgModule (core.js:9170) at new NgModuleRef_ (core.js:9899) at createNgModuleRef (core.js:9888) at Object.debugCreateNgModuleRef [as createNgModuleRef] (core.js:11719) at NgModuleFactory_.push.../../node_modules/@angular/core/fesm5/core.js.NgModuleFactory_.create (core.js:12421) at MapSubscriber.project (router.js:3287) at MapSubscriber.push.../../node_modules/rxjs/_esm5/internal/operators/map.js.MapSubscriber._next (map.js:75) at new FileEffects (file.effects.ts:42) at _createClass (core.js:9260) at _createProviderInstance$1 (core.js:9234) at initNgModule (core.js:9170) at new NgModuleRef_ (core.js:9899) at createNgModuleRef (core.js:9888) at Object.debugCreateNgModuleRef [as createNgModuleRef] (core.js:11719) at NgModuleFactory_.push.../../node_modules/@angular/core/fesm5/core.js.NgModuleFactory_.create (core.js:12421) at MapSubscriber.project (router.js:3287) at MapSubscriber.push.../../node_modules/rxjs/_esm5/internal/operators/map.js.MapSubscriber._next (map.js:75) at resolvePromise (zone.js:814) at resolvePromise (zone.js:771) at zone.js:873 at ZoneDelegate.push.../../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421) at Object.onInvokeTask (core.js:4053) at ZoneDelegate.push.../../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:420) at Zone.push.../../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:188) at drainMicroTaskQueue (zone.js:595)The problem has nothing to do with pipeable operators, but after some digging I found this issue and I can confirm that it has to to with barrel imports. If I reference my effects class from a barrel import...
EffectsModule.forFeature([fromStore.File.FileEffects])...it will compile, but break with the above mentioned error in the browser. If I directly import the effects class and reference it that way...
EffectsModule.forFeature([FileEffects])...everything works as expected.
It should be mentioned that this issue occurs only when compiling with AOT option and the module in question is a lazy-loaded module.
Edit:
I got thinking, in the linked issue, I could see that the barrel re-exports sub-barrels, just like in my case, and creates intermediary module namespaces, like
fromStore.File.FileEffects. So I tried what would happen, if I skip the inner namespace. So instead of:... I would separately import the previously namespaced
Filebarrel like this:This actually works with AOT. So it looks like it's only a problem, for deeper nested re-exports. Maybe it helps to show my store barrel:
Maybe the re-export is done incorrectly?