@ngrxs/states
TypeScript icon, indicating that this package has built-in type declarations

1.1.0 • Public • Published

@ngrxs/states

@ngrxs/states library that provide a common state objects that include selecting, loading and saving metadata.

Installation

npm peer dependency @ngrx/store version

  1. npm install --save @ngrxs/states
    
  2. Import and use SharedState in a state:

    import { SharedState, adapter } from '@ngrxs/states';
    
    export type UsersState = SharedState<Users[], number>;
    export const initialState: UsersState = adapter.getInitialState<User[], number>([]);

Usage

@ngrxs/states provides shared state to hold loaded, loading, saving information and selectors for it.

// filename: users.reducer.ts

import { adapter, SharedState } from '@ngrxs/states';
import { createReducer, on } from '@ngrx/store';

import * as actions from './users.actions';
import { User } from '../models/user';

export type UsersState = SharedState<User[], number>;

export const initialState: UsersState = adapter.getInitialState<User[], number>([]);
export const setUser = adapter.createArraySetter((user: User) => user.id);

export const usersReducer = createReducer(
  initialState,
  on(actions.getAllUsers, state => adapter.loading(state, state.entities)),
  on(actions.allUsersLoaded, (state, { users }) => adapter.loaded(state, users)),
  on(actions.allUsersLoadFail, (state, { error }) => adapter.loadFail(state, error)),
  on(actions.editUser, state => adapter.saving(state)),
  on(actions.editUserSuccess, (state, { user }) => adapter.saved(state, setUser(state, user))),
  on(actions.editUserFailed, (state, { error }) => adapter.saveFail(state, error))
);

adapter Methods

adapter.getInitialLoadableState<T>(value: T)

{
  entities: value,
  loading: {
    error: null,
    loading: false
  },
  loaded: false
}

adapter.getInitialState<T>(value: T)

{
  entities: value,
  loading: {
    error: null,
    loading: false
  },
  loaded: false,
  saving: {
    error: null,
    loading: false
  },
  selectedId: null
}

adapter.select(state: TState, selectedId: TId) => ({ ...state, selectedId })

adapter.loading(state: TState, entities: TData) => ({ ...state, entities, loading: { loading: true, error: null } })

adapter.loaded(state: TState, entities: TData) => ({ ...state, entities, loading: { loading: false, error: null }, loaded: true })

List of Selectors

Selectors Usage
selectEntities Select the state entities
selectSaveState Select the saving state
selectLoadState Select the loading state
selectLoaded Select the loaded value
selectSelectedId Select the selected id

Interfaces

@ngrxs/states exposes interfaces.

LoadableState

{
  error: string | null;
  loading: boolean;
}

SharedLoadableState<TData>

{
  readonly entities: TData;
  readonly loading: LoadableState;
  readonly loaded: boolean;
}

SharedState<TData, TId extends number | string | null>

{
  readonly entities: TData;
  readonly loading: LoadableState;
  readonly loaded: boolean;
  readonly saving: LoadableState;
  readonly selectedId: TId;
}

fetch method

a method fetch fetching state data from service.

fetch(options: {
  id?: (action: TAction) => PropertyKey          // (optional) get the unique id to group results.
  ttl?: number                                   // (optional) when provided it caches the result. ttl is in milliseconds.
  fetch: (action: TAction) => Observable<TData>; // the fetch action
  mapFn: (data: TData) => Action;                // the action mapper function
  errorFn: (error: Error) => Action;             // the error mapper function
})

Example

import { fetch } from '@ngrxs/states';

@Injectable()
export class UsersEffects {
  readonly #actions$ = inject(Actions);
  readonly #service = inject(UsersService);
  
  loadUsers$ = createEffect(() =>
    this.#actions$.pipe(
      ofType(actions.getAllUsers),
      fetch({
        fetch: () => this.#service.getAllUsers(),
        mapFn: payload => actions.allUsersLoaded({ users: payload }),
        errorFn: error => actions.allUsersLoadFail({ error }),
      })
    )
  );

  getUserById$ = createEffect(() =>
    this.#actions$.pipe(
      ofType(actions.getByUserId),
      fetch({
        id: ({ id }) => `user_${id}`,
        ttl: 5_000,
        fetch: ({ id }) => this.#service.getUserById(id),
        mapFn: user => actions.userLoaded({ user }),
        errorFn: error => actions.userLoadFail({ error }),
      })
    )
  );
}

Readme

Keywords

Package Sidebar

Install

npm i @ngrxs/states

Weekly Downloads

12

Version

1.1.0

License

MIT

Unpacked Size

62.9 kB

Total Files

19

Last publish

Collaborators

  • rosenkolev