Reputation: 786
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
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
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
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
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