简体   繁体   中英

How to use NgRx 8 actions with NgRx 7 reducer

I'm using the NgRx library in my new Angular 8 project. I've been told that they create the actions using createAction ie NgRx 8 but they create the reducers using NgRx 7 . I was given a task in which I used NgRx 8 for my reducer which I now have to change to NgRx 7 . My actions and reducer are as below:

book.actions.ts

import { createAction, props } from "@ngrx/store";
import { Book } from "./book";

export const BeginGetBooksAction = createAction("BeginGetBooks");

export const SuccessGetBooksAction = createAction(
  "SuccessGetBooks",
  props<{ payload: Book[] }>()
);

export const BeginAddBookAction = createAction(
  "BeginAddBook",
  props<{ payload: Book }>()
);

export const SuccessAddBookAction = createAction(
  "SuccessAddBook",
  props<{ payload: Book[] }>()
);

book.reducer.ts

import { Action, createReducer, on } from "@ngrx/store";
import * as BooksActions from "./book.action";
import { Book } from "./book";

export interface BooksState {
  Books: Book[];
  ReadBooks: { book: Book; addedOn: Date }[];
  WantToReadBooks: { book: Book; addedOn: Date }[];
  editBook: Book;
}

const initialState: BooksState = {
  Books: [],
  ReadBooks: [],
  WantToReadBooks: [],
  editBook: new Book()
};

export function booksReducer(state = initialState, action: Action) {
  switch (action.type) {
    case BooksActions.BeginGetBooksAction.type:
      return state;

    case BooksActions.SuccessGetBooksAction.type:
      return { ...state, Books: action.payload };

    case BooksActions.BeginAddBookAction.type:
        return state;

    case BooksActions.SuccessAddBookAction.type:
        return { ...state, Books: action.payload };

    default:
      return state;
  }
}

I get an error for action.payload

Property 'payload' does not exist on type 'Action'.

Can someone tell me what I am doing wrong???

I wrote down a comparison in NgRx creator functions 101 .

In the article you can see how you can combine the syntax of both versions:

export const addToCart = createAction(
  // action's type
  '[Product List] Add to cart',
  // optional payload
  props<{ sku: string }>(),
)
export const removeFromCart = createAction(
  '[Product List] Remove from cart',
  props<{ sku: string }>(),
)

export function reducer(
  state = initialState,
  action: ReturnType<typeof addToCart> | ReturnType<typeof removeFromCart>,
) {
  switch (action.type) {
    case addToCart.type:
      return {
        ...state,
        cartItems: {
          ...state.cartItems,
          [action.sku]: (state.cartItems[action.sku] || 0) + 1,
        },
      }

    case removeFromCart.type:
      return {
        ...state,
        cartItems: {
          ...state.cartItems,
          [action.sku]: Math.max((state.cartItems[action.sku] || 0) - 1, 0),
        },
      }

    default:
      return state
  }
}

Your reducer is good, just your type definition is the problem. You use a plain Action type where payload doesn't exists. Try another type definition, like any or try union types, but when you try union types, you need all named imports from the action file. I think the best solution for you is the next generation syntax of reducer, try use the new format.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM