Dim_Ka
Dim_Ka

Reputation: 786

Inject just ngrx feature state in a component

I have a feature state and I would like to inject it in a component. From all the examples that I saw there's only an option to have the global state inject which contains all the feature states. Is it possible to inject just a feature state into a component, and not the entire ngrx store?

Upvotes: 3

Views: 1950

Answers (3)

Alex Fallenstedt
Alex Fallenstedt

Reputation: 2093

You can inject slices of your state into your smart components when you utilize a facade pattern with NgRx.

A facade provides an interface to a set of interfaces in a subsystem. In our example, we want to have an interface for a select part of our store. Take for example the diagram from this article: https://medium.com/@thomasburlesonIA/ngrx-facades-better-state-management-82a04b9a1e39

Facade Design

Structuring a system into subsystems reduces complexity. The facade minimizes communication of ngrx dependencies in components. Rather than importing ngrx like a crazy person, we instead import a single service that represents one feature slice of our store.


@Injectable({
  providedIn: 'root'
})
export class UserFacade {
  constructor(
    private store: Store<AppState>
  ) {}

  public loadUser(): void {
    this.store.dispatch(new fromUserActions.LoadUser());
  }

  public optimisticLoadUser(): void {
    this.user.pipe(
      take(1),
      filter(this.isUserInStoreAlready())
    ).subscribe(() => this.loadUser());
  }

  public get user(): Observable<User> {
    return this.store.pipe(select(fromUserQuey.getUser));
  }
}

You would then create a module for this piece of state and inject that feature into your store

@NgModule({
  declarations: [],
  imports: [
    StoreModule.forFeature(USER_KEY, userReducer),
    EffectsModule.forFeature([UserEffects]),
  ]
})
export class UserStoreModule { }

Now when any component needs information about the user, they can simply inject the UserFacde and use it to communicate to your store.

...
export class SomeSmartComponent {

  constructor(
    private userFacade: UserFacade
  ) { }

...
}

To combine slices of state together from many facades, you can use an app-level facade which consumes many facades into a single facade. I hope this helps you break up your ngrx store into digestible chunks.

Upvotes: 2

timdeschryver
timdeschryver

Reputation: 15505

When you inject Store, you will always have its full state. The generic on the store, e.g. FeatureState on Store<FeatureState>, is only to have type safety in that component at compile time. This is done for string selectors or function selectors, e.g. store.select(s => s.customers). If you're using selectors with the createSelector the generic typing isn't needed anymore, because the selectors themselves are type safe.

At runtime, you will always get the full state.

Upvotes: 5

Frank Adrian
Frank Adrian

Reputation: 1234

You can create a selector, using createSelector which only returns your feature state, see this link for more details: https://ngrx.io/guide/store/selectors#using-a-selector-for-one-piece-of-state

Upvotes: 1

Related Questions