What is @ngrx/component-store?
@ngrx/component-store is a library for managing local/component state in Angular applications. It provides a simple and reactive way to manage state within Angular components, leveraging RxJS for state management and side effects.
What are @ngrx/component-store's main functionalities?
State Management
This feature allows you to manage the state within a component. The `ComponentStore` class is used to define the state and provide methods to update it.
```typescript
import { ComponentStore } from '@ngrx/component-store';
interface State {
count: number;
}
@Injectable()
class CounterStore extends ComponentStore<State> {
constructor() {
super({ count: 0 });
}
readonly increment = this.updater((state) => ({ count: state.count + 1 }));
readonly decrement = this.updater((state) => ({ count: state.count - 1 }));
readonly reset = this.updater(() => ({ count: 0 }));
}
```
Selectors
Selectors are used to derive and expose slices of the state. The `select` method allows you to create observables that emit state changes.
```typescript
@Injectable()
class CounterStore extends ComponentStore<State> {
constructor() {
super({ count: 0 });
}
readonly count$ = this.select(state => state.count);
}
```
Effects
Effects are used to handle side effects, such as HTTP requests. The `effect` method allows you to define observables that can trigger state changes based on external events.
```typescript
@Injectable()
class CounterStore extends ComponentStore<State> {
constructor(private readonly http: HttpClient) {
super({ count: 0 });
}
readonly loadCount = this.effect((trigger$) =>
trigger$.pipe(
switchMap(() => this.http.get<number>('/api/count').pipe(
tapResponse(
(count) => this.patchState({ count }),
(error) => console.error(error)
)
))
)
);
}
```
Other packages similar to @ngrx/component-store
ngxs
NGXS is a state management library for Angular that is modeled after the Redux pattern. It provides a more opinionated and structured approach to state management compared to @ngrx/component-store, with features like actions, selectors, and middleware.
akita
Akita is a state management library for Angular applications that focuses on simplicity and performance. It provides a more flexible and less opinionated approach compared to @ngrx/component-store, with features like entity stores and query services.
angular-redux
Angular-Redux is a library that integrates Redux with Angular. It provides a way to manage global state using the Redux pattern, which can be more complex and boilerplate-heavy compared to the local state management provided by @ngrx/component-store.
16.0.0-beta.0 (2023-04-27)
Bug Fixes
- data: allow 0 to be a valid key (#3830) (e50126d), closes #3828
- effects: run user provided effects defined as injection token (#3851) (cdaeeb6), closes #3848
- store: correctly infer action group events defined as empty object (#3833) (dc78447)
- store-devtools: correctly import state when feature is set to true (#3855) (0df3419), closes #3636
Features
- component-store: add selectSignal method for interop with Angular Signals (#3861) (195d5ac)
- component-store: add tapResponse signature with observer object (#3829) (3a5e5d8)
- effects: accept ObservableInput as concatLatestFrom argument (#3838) (34dd28c)
- router-store: add @nrwl/angular data persistence operators (#3841) (4482751), closes #3777
- router-store: remove deprecated getSelectors method (#3816) (351a75e), closes #3815
- schematics: replace
any
type with unknown
type (#3827) (0ea2933) - schematics: Use createActionGroup in schematics (#3791) (f6ce20f)
- store: add createMockStore migration (#3810) (ded4240)
- store: add selectSignal method for interop with Angular Signals (#3856) (999dcb6)
- store: preserve the event name case with createActionGroup (#3832) (482fa5d)
- store: remove deprecated createFeature method (#3825) (fd8f347), closes #3814
- store: remove forbidden chars and empty str checks from createActionGroup (#3857) (e37c57b)
- convert entity and router selectors interfaces to types (#3853) (73eb55c)
- store: remove getMockStore in favor of createMockStore (#3835) (8d0ed8e)
- store: use strict projectors for createFeature selectors (#3799) (bafd121)
- update to Angular v16.0.0-next.6 release (#3831) (d7e03df)
BREAKING CHANGES
- store: The event name case is preserved when converting to the action name by using the
createActionGroup
function.
BEFORE:
All letters of the event name will be lowercase, except for the initial letters of words starting from the second word, which will be uppercase.
const authApiActions = createActionGroup({
source: 'Auth API',
events: {
'LogIn Success': emptyProps(),
'login failure': emptyProps(),
'Logout Success': emptyProps(),
logoutFailure: emptyProps(),
},
});
// generated actions:
const { loginSuccess, loginFailure, logoutSuccess, logoutfailure } = authApiActions;
AFTER:
The initial letter of the first word of the event name will be lowercase, and the initial letters of the other words will be uppercase. The case of other letters in the event name will remain the same.
const { logInSuccess, loginFailure, logoutSuccess, logoutFailure } = authApiActions;
- store: The
createFeature
signature with root state is removed in favor of a signature without root state.
An automatic migration is added to remove this signature.
BEFORE:
interface AppState {
users: State;
}
export const usersFeature = createFeature<AppState>({
name: 'users',
reducer: createReducer(initialState /* case reducers */),
});
AFTER:
export const usersFeature = createFeature({
name: 'users',
reducer: createReducer(initialState /* case reducers */),
});
- router-store: The deprecated
getSelectors
function has been removed from the @ngrx/router-store
package.
BEFORE:
The @ngrx/router-store package exports the getSelectors
function.
AFTER:
The @ngrx/router-store package no longer exports the getSelectors
function. A migration has been provided to replace existing usage
- schematics: NgRx Schematics do not use
any
types to define actions, these are replaced with the unknown
type.
BEFORE:
Schematics used the any
type to declare action payload type.
AFTER:
Schematics use the unknown
type to declare action payload type.
- store: The
getMockStore
function is removed in favor of createMockStore
BEFORE:
import { getMockStore } from '@ngrx/store/testing';
const mockStore = getMockStore();
AFTER:
import { createMockStore } from '@ngrx/store/testing';
const mockStore = createMockStore();
- store: Projectors of selectors generated by createFeature are strongly typed.
BEFORE:
Projector function arguments of selectors generated by createFeature are not strongly typed:
const counterFeature = createFeature({
name: 'counter',
reducer: createReducer({ count: 0 }),
});
counterFeature.selectCount.projector;
// type: (...args: any[]) => number
AFTER:
Projector function arguments of selectors generated by createFeature are strongly typed:
const counterFeature = createFeature({
name: 'counter',
reducer: createReducer({ count: 0 }),
});
counterFeature.selectCount.projector;
// type: (featureState: { count: number; }) => number
<a name="15.4.0"></a>