Description
In this Minimal Reproductible Example I don't understand why the reducer has something (we can observe it in the ReduxDevTools) but the selector puts undefined in the component.
Could someone have keys to share about this behavior?
Codes
Here are the parts of the MRE:
- actions/index.ts
import { createAction } from '@ngrx/store';
export const µAppInitializerEntered = createAction(`[frontend] µAppInitializerEntered`);
- components/index.html
<pre>{{ feature$ | async | json }}</pre>
- components/index.ts
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { select, Store } from '@ngrx/store';
import { $feature } from '../selectors';
import { tap } from 'rxjs/operators'
@Component({
selector: 'workspace-index',
templateUrl: './index.component.html',
styleUrls: ['./index.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class IndexComponent {
feature$ = this.store.pipe(select($feature), tap(feature => {
console.log({ feature })
}))
constructor(private store: Store<{}>) { }
}
- reducers/app-initializer/index.reducer.ts
import { createReducer, on } from '@ngrx/store';
import { produce } from 'immer';
import { µAppInitializerEntered } from '../../actions';
export interface AppInitializer {
status: 'initial' | 'entered';
}
export const appInitializer = createReducer(
{
status: 'initial' as AppInitializer['status']
},
on(µAppInitializerEntered, (state): AppInitializer => produce(state, (draft) => {
draft.status = 'entered';
}))
);
- reducers/index.ts
import { InjectionToken } from '@angular/core';
import { Action, ActionReducerMap, MetaReducer } from '@ngrx/store';
import { appInitializer, AppInitializer } from './app-initializer/index.reducer';
export interface FeatureState {
appInitializer: AppInitializer;
}
export interface State {
frontend: FeatureState;
}
export const reducers = new InjectionToken<ActionReducerMap<FeatureState, Action>>('frontend', {
factory: () => ({ appInitializer })
});
- selectors/index.ts
import { createFeatureSelector, createSelector } from '@ngrx/store';
import { FeatureState, State } from '../reducers';
export const $feature = createFeatureSelector<State, FeatureState>('frontend');
export const $appInitializer = createSelector($feature, (feature) => feature?.appInitializer);
export const $appInitializerEntered = createSelector($appInitializer, (appInitializer) => appInitializer?.status);
- index.module.ts
import { APP_INITIALIZER, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { Store, StoreModule } from '@ngrx/store';
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
import { µAppInitializerEntered } from './actions';
import { IndexComponent } from './components/index.component';
import { reducers } from './reducers';
@NgModule({
bootstrap: [IndexComponent],
declarations: [IndexComponent],
imports: [
BrowserModule,
StoreModule.forRoot(reducers, {
runtimeChecks: {
strictActionImmutability: true,
strictActionSerializability: true,
strictStateImmutability: true,
strictStateSerializability: true
}
}),
StoreDevtoolsModule.instrument({
maxAge: 5000,
name: 'frontend'
})
],
providers: [
{
provide: APP_INITIALIZER,
useFactory: (store: Store<{}>) => () => store.dispatch(µAppInitializerEntered()),
multi: true,
deps: [Store]
}
]
})
export class AppModule {
}
Context
- package.json#dependencies
"@angular/animations": "^10.1.0",
"@angular/common": "^10.1.0",
"@angular/compiler": "^10.1.0",
"@angular/core": "^10.1.0",
"@angular/forms": "^10.1.0",
"@angular/platform-browser": "^10.1.0",
"@angular/platform-browser-dynamic": "^10.1.0",
"@angular/platform-server": "^10.1.0",
"@angular/router": "^10.1.0",
"@ngrx/effects": "^10.0.1",
"@ngrx/router-store": "^10.0.1",
"@ngrx/store": "^10.0.1",
"@nrwl/node": "^10.4.4",
"angular-oauth2-oidc": "^10.0.3",
"immer": "^8.0.0",
"lodash.random": "^3.2.0",
"rxjs": "~6.5.5",
"tslib": "^2.0.0",
"zone.js": "^0.10.2"
- yarn run nx report
yarn run v1.21.1
$ nx report
> NX Report complete - copy this into the issue template
nx : Not Found
@nrwl/angular : 10.4.4
@nrwl/cli : 10.4.4
@nrwl/cypress : 10.4.4
@nrwl/eslint-plugin-nx : 10.4.4
@nrwl/express : Not Found
@nrwl/jest : 10.4.4
@nrwl/linter : 10.4.4
@nrwl/nest : Not Found
@nrwl/next : Not Found
@nrwl/node : 10.4.4
@nrwl/react : Not Found
@nrwl/schematics : Not Found
@nrwl/tao : 10.4.4
@nrwl/web : Not Found
@nrwl/workspace : 10.4.4
typescript : 4.0.5
Done in 1.68s.
Notes
I originally posted this issue on @ngrx/platform repo (here) rather than in here in StackOverflow because I tried to follow the NgRx documentation very carefully to do this MRE so I thought that maybe I missed a documentation somewhere which we can bring more visibility on in the official documentation.