[ ] Regression (a behavior that used to work and stopped working in a new release)
[x ] Bug report
[ ] Feature request
[ ] Documentation issue or request
Error message displayed in console
Chrome current ver (63) 64bit
npm ver 5.5.1
node ver 8.9.1
angular 5.1.0
rxjs 5.5.2
ngrx 4.1.1
Typescript 2.6.2
app.module.ts
...
imports: [
...
SharedModule,
HttpClientModule,
StoreModule.forRoot(reducers, {metaReducers}),
EffectsModule.forRoot([]),
StoreDevtoolsModule.instrument({
maxAge: 25,
}),
...
app/reducers/index.ts
...
export interface State { }
export const reducers: ActionReducerMap<State> = { };
export function logger(reducer: ActionReducer<State>): ActionReducer<State> {
return function(state: State, action: any): State {
console.log('state', state);
console.log('action', action);
return reducer(state, action);
};
}
export const metaReducers: MetaReducer<State>[] = !environment.production
? [logger]
: [];
app/store/supplier/reducers/supplier.reducer.ts
export const supplierAdapter = createEntityAdapter<Supplier>();
export interface State extends EntityState<Supplier> { }
export const initialState: State = supplierAdapter.getInitialState();
export function supplierReducer (
state: State = initialState,
action: actions.SupplierActions) {
switch (action.type) {
case actions.CREATE:
return supplierAdapter.addOne(action.supplier, state);
case actions.UPDATE:
return supplierAdapter.updateOne({
id: action.id,
changes: action.changes,
}, state);
case actions.DELETE:
return supplierAdapter.removeOne(action.id, state);
case actions.LOAD_SUCCESS:
return supplierAdapter.addMany(action.suppliers, state);
default:
return state;
}
}
app/store/supplier/supplier.actions.ts
import { Supplier } from './supplier.models';
import { Action } from '@ngrx/store';
export const CREATE = '[Suppliers] Create';
export const UPDATE = '[Suppliers] Update';
export const DELETE = '[Suppliers] Delete';
export const SEARCH = '[Suppliers] Search';
export const SEARCH_COMPLETE = '[Suppliers] Search Complete';
export const LOAD = '[Suppliers] Load';
export const LOAD_SUCCESS = '[Suppliers] Load Success';
export const LOAD_FAILURE = '[Suppliers] Load Failed';
export class Create implements Action {
readonly type = CREATE;
constructor(public supplier: Supplier) {}
}
export class Update implements Action {
readonly type = UPDATE;
constructor(
public id: string,
public changes: Partial<Supplier>,
) {}
}
export class Delete implements Action {
readonly type = DELETE;
constructor(public id: string) { }
}
export class Load implements Action {
readonly type = LOAD;
constructor() { }
}
export class LoadSuccess implements Action {
readonly type = LOAD_SUCCESS;
constructor(public suppliers: Supplier[]) { }
}
export class LoadFailure implements Action {
readonly type = LOAD_FAILURE;
constructor(public error: any) { }
}
export class Search implements Action {
readonly type = SEARCH;
constructor(public query: string) { }
}
export class SearchComplete implements Action {
readonly type = SEARCH_COMPLETE;
constructor(public payload: any) { }
}
export type SupplierActions
= Create
| Update
| Delete
| Load
| LoadSuccess
| LoadFailure
| Search
| SearchComplete;
app/store/supplier/supplier.effects.ts
...
export const SEARCH_DEBOUNCE = new InjectionToken<number>('Search Debounce');
export const SEARCH_SCHEDULER = new InjectionToken<Scheduler>(
'Search Scheduler',
);
@Injectable()
export class SupplierEffects {
@Effect()
loadSuppliers$: Observable<Action> = this.actions$
.ofType(supplier.LOAD)
.switchMap(() =>
this.supplierService.getAll()
.map((suppliers: Supplier[]) => new supplier.LoadSuccess(suppliers))
.catch((error: any) => of(new supplier.LoadFailure(error))),
);
constructor(
private actions$: Actions,
private supplierService: SupplierService,
) {}
}
app/store/supplier/supplier.services.ts
app/store/supplier/supplier.models.ts
also: app/store/account/... <-- same as app/store/supplier...
app/references/references.module.ts <-- feature module
...
import * as reducers from './reducers';
@NgModule({
imports: [
CommonModule,
StoreModule.forFeature('references', reducers),
EffectsModule.forFeature([SupplierEffects, AccountEffects]),
RouterModule.forChild([
{ path: '', component: SupplierListComponent },
{ path: 'suppliers', component: SupplierListComponent },
// { path: 'accounts', component: AccountListComponent},
]),
],
declarations: [SupplierListComponent],
providers: [SupplierService, AccountService],
})
export class ReferencesModule { }
app/references/reducers/index.ts
import { createSelector, createFeatureSelector, StoreModule, ActionReducerMap } from '@ngrx/store';
import * as fromRoot from '../../reducers';
import * as fromSupplierSearch from '../../store/supplier/reducers/search.reducer'
import * as fromSuppliers from '../../store/supplier/reducers/supplier.reducer';
import * as fromAccountSearch from '../../store/account/reducers/search.reducer'
import * as fromAccounts from '../../store/account/reducers/account.reducer';
export interface State {
'supplier': SupplierState;
'account': AccountState;
}
export interface SupplierState {
supplierSearch: fromSupplierSearch.State;
suppliers: fromSuppliers.State;
}
export interface AccountState {
acccountSearch: fromAccountSearch.State;
accounts: fromAccounts.State;
}
export interface State extends fromRoot.State {
'suppliers': SupplierState;
'accounts': AccountState;
}
export const reducers: ActionReducerMap<any> = {
supplierSearch: fromSupplierSearch.reducer,
suppliers: fromSuppliers.supplierReducer,
accountSearch: fromAccountSearch.reducer,
accounts: fromAccounts.accountReducer,
};
<=== FAILURE occurs here
export const getSupplierState = createFeatureSelector<SupplierState>("suppliers"); **<== FAILS HERE! WITH "Cannot read property 'suppliers' of undefined" in Chrome console**
* * * According to Chrome redux devtools at @ngrx/store/init - message is "Cannot read property 'suppliers' of undefined * * *
* * * According to Chrome redux devtools all other states: "Interrupted by an error up the chain" * * *
===> END FAILURE
export const getAccountState = createFeatureSelector<AccountState>('accounts');
export const getSupplierEntitiesState = createSelector(
getSupplierState,
state => state.suppliers
);
export const getAccountEntitiesState = createSelector(
getAccountState,
state => state.accounts
);
export const {
selectIds: getSupplierIds,
selectEntities: getSupplierEntities,
selectAll: getAllSuppliers,
selectTotal: getTotalSuppliers,
} = fromSuppliers.supplierAdapter.getSelectors(getSupplierEntitiesState);
export const {
selectIds: getAccountIds,
selectEntities: getAccountEntities,
selectAll: getAllAccounts,
selectTotal: getTotalAccounts,
} = fromAccounts.accountAdapter.getSelectors(getAccountEntitiesState);
app/references/supplier/supplier-list/supplier-list.component.ts
import { Component, OnInit } from '@angular/core';
import * as actions from '../../../store/supplier/supplier.actions';
import * as fromSupplier from '../../reducers';
import { Observable } from 'rxjs/Observable';
import { Store } from '@ngrx/store';
@Component({
selector: 'uni-supplier-list',
templateUrl: './supplier-list.component.html',
styleUrls: ['./supplier-list.component.scss']
})
export class SupplierListComponent implements OnInit {
suppliers: Observable<any>;
constructor(private store: Store<fromSupplier.State>) { }
ngOnInit() {
this.store.dispatch(new actions.Load());
this.suppliers = this.store.select(fromSupplier.getAllSuppliers);
}
}
Thank you!
This doesn't look like a bug in ngrx to me. Your suppliers state is under the references top level feature state. So you need to select the references state, and compose a selector to select the suppliers state.
Thank you Brandon - - that was quick! How do you "select the references state and compose a selector to select the suppliers state"?
Thanks!
Example
export const getReferencesState = createFeatureSelector<State>('references');
export const getSupplierState = createSelector(getReferencesState, state => state.suppliers);
Now getting console error: "TypeError: Cannot read property 'references' of undefined".
A reproduction in plunker or stackblitz will be easier to diagnose. Is the ReferencesModule lazy loaded or included in the App module?
It's lazy loaded.
Including ReferencesModule in app.module triggers the same error in the console - - but unlike the previous example, it triggers the error message twice.

Are all your reducers returning a default in your switch cases? Also post a screenshot of your state in the Devtools at the time of the error if possible
There's not all that much to show. Here is the screen image of the state at @ngrx/store/init. All the other action states are "Interrupted by an error up the chain".

Oh and yes. All of the reducers have a default in the switch statements that return the current state.
@ccpony
I found you'd have contributions more eager to help if they can work with some actual code that has the error: https://stackblitz.com/ is an awesome tool to quickly create an project so that it can be looked at. While creating that project you might actually find the source of the issue yourself when you try to reproduce it.
Here is the slackblitz (editor): https://stackblitz.com/edit/angular-uniformax
and the slackblitz (app): https://angular-uniformax.stackblitz.io
Please navigate to: https://angular-uniformax.stackblitz.io/#/references/suppliers
Still generates the "cannot read property 'references' of undefined" error. Hope this helps.
@ccpony the error is in your references.module.ts on line 13. You have a wildcard export
import * as reducers from './reducers';
and line 23 has
StoreModule.forFeature('references', reducers),
It should be
import * as fromReferences from './reducers';
and
StoreModule.forFeature('references', fromReferences.reducers),
By George, I think he's got it! Thanks Brandon, for the quick response AND for pointing me towards stackblitz. - - Jeff
Thank you Brandon, this helped me a lot as well !
Hey, I am having the same issue but only in production build. Now I am not sure if this is a bug or if I am doing a mistake.
I get the error " "TypeError: Cannot read property 'release' of undefined"." in the console, if I load the following feature module with ngrx:
import { AccountDto } from '../../../dto';
import * as fromAccountActions from '../actions/account.actions';
export interface AccountState {
loading: boolean;
loaded: boolean;
accountItems: AccountDto[];
}
export const initialState: AccountState = {
loading: false,
loaded: false,
accountItems: []
};
export function accountReducer(
state = initialState,
action: fromAccountActions.AccountActions
): AccountState {
switch (action.type) {
case fromAccountActions.LOAD_ACCOUNT: {
// console.log(action.type);
return { ...state, loading: true };
}
case fromAccountActions.LOAD_ACCOUNT_FINISHED: {
console.log('Finished: ' + action.payload);
return {
...state,
loading: false,
loaded: true,
accountItems: action.payload
};
}
case fromAccountActions.LOAD_ACCOUNT_FAILED: {
return {
...state,
loading: false,
loaded: false,
accountItems: []
};
}
}
}
// gibt die teile des States
export const getAccountItems = (state: AccountState) => state.accountItems;
export const getAccountLoading = (state: AccountState) => state.loading;
export const getAccountLoaded = (state: AccountState) => state.loaded;
index.ts in reducers
import * as fromReducer from './account.reducers';
import { ActionReducerMap } from '@ngrx/store';
import { createFeatureSelector } from '@ngrx/store';
export interface AccountState {
account: fromReducer.AccountState;
}
export const reducers: ActionReducerMap<AccountState> = {
account: fromReducer.accountReducer
};
export const getAccountState = createFeatureSelector<AccountState>('account');
account.selectors.ts
import { createSelector } from '@ngrx/store';
import * as fromReducer from '../reducers/account.reducers';
import * as fromFeature from '../reducers';
export const getCompleteAccountState = createSelector(
fromFeature.getAccountState,
(state: fromFeature.AccountState) => state.account
);
export const getAccountLoading = createSelector(
this.getCompleteAccountState,
fromReducer.getAccountLoading
);
export const getAccountLoaded = createSelector(
this.getCompleteAccountState,
fromReducer.getAccountLoaded
);
export const getAllAccountItems = createSelector(
this.getCompleteAccountState,
fromReducer.getAccountItems
);
account.module.ts
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { TranslateModule } from '@ngx-translate/core';
import { ThirdPartyModule } from '../thirdParty/thirdParty.module';
import { SharedModule } from './../shared/shared.module';
import { AccountListComponent } from './account-list/account-list.component';
import { AccountRoutesModule } from './account.routes';
import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
import { reducers, AccountEffects } from 'app/+account/store';
@NgModule({
imports: [
CommonModule,
FormsModule,
SharedModule,
AccountRoutesModule,
ThirdPartyModule,
TranslateModule,
StoreModule.forFeature('account', reducers),
EffectsModule.forFeature([AccountEffects])
],
declarations: [AccountListComponent],
providers: [],
exports: []
})
export class AccountModule {}
Help would be very much appreciated.
Thanks, Fabian
@FabianGosebrink Your switch statement in your reducer is missing a default return of the provided state.
@brandonroberts thank you for your answer.
export function accountReducer(
state = initialState,
action: fromAccountActions.AccountActions
): AccountState {
switch (action.type) {
case fromAccountActions.LOAD_ACCOUNT: {
// console.log(action.type);
return { ...state, loading: true };
}
case fromAccountActions.LOAD_ACCOUNT_FINISHED: {
console.log('Finished: ' + action.payload);
return {
...state,
loading: false,
loaded: true,
accountItems: action.payload
};
}
case fromAccountActions.LOAD_ACCOUNT_FAILED: {
return {
...state,
loading: false,
loaded: false,
accountItems: []
};
}
default:
return state;
}
}
had this in the procedure of finding the error. Resetted the code one step too far. So the reducer above unfortunately gives the same error. "TypeError: Cannot read property 'release' of undefined".
Cheers, Fabian
Any update on that issue? Still trying to get it working, but production build gives the error on runtime.
@FabianGosebrink https://github.com/ngrx/platform/issues/645#issuecomment-351787150
Will create a sample repo and provide it here as soon as I got it stripped down to the essential issue. Thanks!
I created this repository https://github.com/FabianGosebrink/16.01.2018 which shows the issue even without the production build. Hope this helps to reproduce the issue.
@FabianGosebrink you're missing some required dependencies. Here is a working fork https://github.com/brandonroberts/16.01.2018/commit/26f22603773cf90214597e0d3841bded2fa9ab36
Added the missing modules. Thanks for pointing out. But doing a production build leads to the same error...
@FabianGosebrink I ran ng serve -prod -o on my fork and it still worked correctly. If you can update your fork to more accurately reproduce the issue it would help. The gitter channel is also a valuable resource.
I am starting to think that this is any version related problem. Will try this again at home, but just for my info: Which version of tsc are you running?
I used the version that was installed in the fork 2.4.2
I got it! Gosh...did not think that it was that one, but it was the this in the selector. Did not see the change in your repo @brandonroberts .
import { createSelector } from '@ngrx/store';
import * as fromReducer from '../reducers/account.reducers';
import * as fromFeature from '../reducers';
export const getCompleteAccountState = createSelector(
fromFeature.getAccountState,
(state: fromFeature.AccountState) => state.account
);
export const getAccountLoading = createSelector(
getCompleteAccountState,
fromReducer.getAccountLoading
);
export const getAccountLoaded = createSelector(
getCompleteAccountState,
fromReducer.getAccountLoaded
);
export const getAllAccountItems = createSelector(
getCompleteAccountState,
fromReducer.getAccountItems
);
works well. THANK YOU EVERYONE for the time and help!
Cheers, Fabian
@brandonroberts
_Your switch statement in your reducer is missing a default return of the provided state._
Man, thanks for this! You've saved me ton of time.
Did a number of ngrx things and all of the sudden started getting this 'very strange' error. Completely forgot about default: return state;
Thanks a ton!
In case it can help anyone, for me it was because I had some circular dependencies in my selectors.
Fixed that, and the error's gone!
It happened for me because I was missing the module import where I had the feature store.
also make sure the createFeatureSelector name matches the StoreModule.forRoot name
I had this issue my variable was getting cAlled before it was initialized when my component was loaded. was able to track it down with the timeline debugging. My problem was in my component I used my components state when I initialized the store once I initialized with the root store problems went away
also make sure the createFeatureSelector name matches the StoreModule.forRoot name
U saved my life man 馃憤
Most helpful comment
Are all your reducers returning a default in your switch cases? Also post a screenshot of your state in the Devtools at the time of the error if possible