Modifying your Application State by Dispatching Actions

Most Redux apps have a set of functions, called "action creators", that areused to set up and dispatch actions.

In Angular, it's convenient to define your action creators as @Injectable() services, decoupling the dispatch, creation and side-effect logic from the @Component classes in your application.

Synchronous Actions

Here is a simple example:

app/store/counter/counter.actions.ts

  1. import {Injectable} from '@angular/core';
  2. import {Store} from '@ngrx/store';
  3. import {createAction} from '../createAction';
  4. import {AppState} from '../../models/appState';
  5. @Injectable()
  6. export class CounterActions {
  7. static INCREMENT = 'INCREMENT';
  8. static DECREMENT = 'DECREMENT';
  9. static RESET = 'RESET';
  10. constructor(private store: Store<AppState>) {
  11. }
  12. increment() {
  13. this.store.dispatch(createAction(CounterActions.INCREMENT));
  14. }
  15. decrement() {
  16. this.store.dispatch(createAction(CounterActions.DECREMENT));
  17. }
  18. reset() {
  19. this.store.dispatch(createAction(CounterActions.RESET));
  20. }
  21. }

As you can see, the action creators are simple functions that dispatch Action objects containing more information that describes the state modification.

Asynchronous Actions

This "ActionCreatorService" pattern comes in handy if you must handleasynchronous or conditional actions (users of react-redux may recognize thispattern as analogous to redux-thunk in a dependency-injected world).

app/store/counter/counter.actions.ts

  1. import {Injectable} from '@angular/core';
  2. import {Store} from '@ngrx/store';
  3. import {createAction} from '../createAction';
  4. import {AppState} from '../../models/appState';
  5. @Injectable()
  6. export class CounterActions {
  7. constructor(private store: Store<AppState>) {
  8. }
  9. incrementIfOdd() {
  10. this.store.select(appState => appState.counter.currentValue)
  11. .take(1)
  12. .subscribe(currentValue => {
  13. if (currentValue % 2 !== 0) {
  14. this.store.dispatch(createAction(CounterActions.INCREMENT);
  15. }
  16. });
  17. }
  18. incrementAsync(timeInMs: number = 1000) {
  19. this.delay(timeInMs).then(() => this.store.dispatch(createAction(CounterActions.INCREMENT)));
  20. }
  21. private delay(timeInMs: number) {
  22. return new Promise((resolve) => {
  23. setTimeout(() => resolve() , timeInMs);
  24. });
  25. }
  26. }

In the incrementIfOdd() action creator, we create a one-time subscription to the counter's currentValue in the application state. From there, we check to see if it's odd before dispatching an action.

In the incrementAsync() action creator, we are delaying the actual call to dispatch(). We created a Promise that will resolve after the delay. Oncethe Promise resolves, we can then dispatch an action to increment the counter.

Actions that Depend on Other Services

The ActionCreatorService pattern becomes necessary in cases where your actioncreators must use other Angular services. Consider the followingSessionActions service that handles a remote API call:

  1. import {Injectable} from '@angular/core';
  2. import {Store} from '@ngrx/store';
  3. import {createAction} from '../createAction';
  4. import {AppState} from '../../models/appState';
  5. @Injectable()
  6. export class SessionActions {
  7. static LOGIN_USER_PENDING = 'LOGIN_USER_PENDING';
  8. static LOGIN_USER_SUCCESS = 'LOGIN_USER_SUCCESS';
  9. static LOGIN_USER_ERROR = 'LOGIN_USER_ERROR';
  10. static LOGOUT_USER = 'LOGOUT_USER';
  11. constructor(
  12. private store: Store<AppState>,
  13. private authService: AuthService
  14. ) {
  15. }
  16. loginUser(credentials: any) {
  17. this.store.dispatch(createAction(SessionActions.LOGIN_USER_PENDING));
  18. this.authService.login(credentials.username, credentials.password)
  19. .then(result => this.store.dispatch(createAction(SessionActions.LOGIN_USER_SUCCESS, result)))
  20. .catch(() => this.store.dispatch(createAction(SessionActions.LOGIN_USER_ERROR)));
  21. };
  22. logoutUser() {
  23. this.store.dispatch(createAction(SessionActions.LOGOUT_USER));
  24. };
  25. }

原文: https://angular-2-training-book.rangle.io/handout/state-management/ngrx/modifying_your_application_state_by_dispatching_actions.html