ngrx / store-angular-状态不保存某些数据

问题描述 投票:0回答:1

我有一个购物商店应用程序,可以在其中管理产品状态和购物车状态。

在加载产品页面时,我从服务器获取了所有产品,并在redux开发工具中看到了它们。一旦我在购物车中添加了商品,购物车的状态就会更新,但是该状态下所有产品都丢失了,我在页面上再也看不到它们。

在将商品添加到购物车之前:how the state looks

将商品添加到购物车后:the state

我如何在不删除产品状态的情况下将商品添加到购物车,以免为空?

app.state:

 import { CartState } from './cart/cart.state';
import ProductState from './product/product.state';

export interface AppState {
  product: ProductState;
  cart: CartState;
}

app.reducers

import { cartReducer } from './cart/cart.reducers';
import { productReducer } from './product/product.reducers';

export const appReducers = {
  product: productReducer,
  cart: cartReducer
};

cart.actions

import { Action } from '@ngrx/store';
import { CartProductModel } from '../../models/cart/cart.model';

export const ADD_TO_CART = '[CART] ADD';
export const UPDATE_CART = '[CART] UPDATE CART';
export const REMOVE_FROM_CART = '[CART] REMOVE';
export const CLEAR_CART = '[CART] CLEAR';

export class AddToCart implements Action {
  readonly type: string = ADD_TO_CART;

  constructor(public payload: CartProductModel) {}
}

export class UpdateCart implements Action {
  readonly type: string = UPDATE_CART;

  constructor(public id: string, public quantity: number) {}
}

export class RemoveFromCart implements Action {
  readonly type: string = REMOVE_FROM_CART;

  constructor(public id: string) {}
}

export class ClearCart implements Action {
  readonly type: string = CLEAR_CART;
}

cart.reducers

import { CartState } from './cart.state';
import { AppState } from '../app.state';
import {
  ADD_TO_CART,
  UPDATE_CART,
  REMOVE_FROM_CART,
  CLEAR_CART
} from './cart.actions';
import { CartProductModel } from '../../models/cart/cart.model';

const initialState: CartState = {
  products: []
};

function addToCart(state: CartState, product: CartProductModel) {
  if (state.products.find(p => p._id === product._id)) {
    const newProducts = state.products.slice();
    const cartProduct = newProducts.find(p => p._id === product._id);
    cartProduct.quantity = +1;
    return {
      ...state,
      products: newProducts
    };
  }


  return {
    ...state,
    products: [...state.products, product]
  };
}

function updateCart(state: CartState, id: string, quantity: number) {
  // debugger
  const newProducts = state.products.slice();
  const cartProduct = newProducts.find(p => p._id === id);
  cartProduct.quantity = quantity;

  return {
    ...state,
    products: newProducts
  };
}

function removeFromCart(state: CartState, id: string) {
  return {
    ...state,
    products: [...state.products.filter(p => p._id !== id)]
  };
}

function clearCart(state) {
  return {
    ...state,
    products: []
  };
}

export function cartReducer(state: CartState = initialState, action) {
  switch (action.type) {
    case ADD_TO_CART:
      return addToCart(state, action.payload);

    case UPDATE_CART:
      return updateCart(state, action.id, action.quantity);

    case REMOVE_FROM_CART:
      return removeFromCart(state, action.id);

    case CLEAR_CART:
      return clearCart(state);
    default:
      return state;
  }
}

cart.state

import { CartProductModel } from '../../models/cart/cart.model';

export interface CartState {
  readonly products: CartProductModel[];
}

product.actions

 import { Action } from '@ngrx/store';
    import ProductModel from '../../models/product/product.model';

    export const GET_ALL_PRODUCTS = '[PRODUCT] GET ALL';
    export const CREATE_PRODUCT = '[PRODUCT] CREATE';
    export const EDIT_PRODUCT = '[PRODUCT] EDIT';

    export class GetAllProducts implements Action {
      type: string = GET_ALL_PRODUCTS;
      constructor(public payload: ProductModel[]) {}
    }

    export class CreateProduct implements Action {
      type: string = CREATE_PRODUCT;
      constructor(public payload) {}
    }

    export class EditProduct implements Action {
      type: string = EDIT_PRODUCT;
      constructor(public payload) {}
    }



    export type Types = GetAllProducts | CreateProduct | EditProduct;

product.reducers
import ProductState from './product.state';
import * as ProductActions from './product.actions';

const initialState: ProductState = {
  all: []
};

function getAllProducts(state, action) {
  return {
    ...state,
    all: action
  };
}

function createProduct(state, action) {
  return {
    ...state,
    all: [...state.all, action]
  };
}

function editProduct(state, action) {
  return {
    ...state,
    all: [...state.all.filter(p => p._id !== action._id), action]
  };
}


export function productReducer(
  state: ProductState = initialState,
  action: ProductActions.Types
) {
  switch (action.type) {
    case ProductActions.GET_ALL_PRODUCTS:
      return getAllProducts(state, action.payload);

    case ProductActions.CREATE_PRODUCT:
      return createProduct(state, action.payload);

    case ProductActions.EDIT_PRODUCT:
      return editProduct(state, action.payload);


    default:
      return initialState;
  }
}

product.state

    import ProductModel from '../../models/product/product.model';

export default interface ProductState {
  all: ProductModel[];
}

产品list.component

import { Component, OnInit, Output, DoCheck } from '@angular/core';
import { NgxSpinnerService } from 'ngx-spinner';
import { ProductService } from 'src/app/core/services/product.service';
import { Store } from '@ngrx/store';
import { AppState } from 'src/app/core/store/app.state';
import { animations } from './product-list-animation';
import { Subscription } from 'rxjs';
import ProductModel from 'src/app/core/models/product/product.model';

@Component({
  selector: 'app-product-list',
  templateUrl: './product-list.component.html',
  styleUrls: ['./product-list.component.scss'],
  animations: animations
})
export class ProductListComponent implements OnInit {
  @Output()
  products: ProductModel[];

  subscribe$: Subscription[] = [];

  protected pageSize: number = 6;
  currentPage: number = 1;
  constructor(
    private spinner: NgxSpinnerService,
    private productService: ProductService,
    private store: Store<AppState>
  ) {}

  ngOnInit() {
    this.spinner.show();
    this.productService.getAllProducts();

    this.subscribe$.push(
      this.store
        .select<ProductModel[]>(state => state.product.all)
        .subscribe(products => {
          this.products = products;
          this.spinner.hide();
        })
    );
  }

  changePage(page) {
    this.currentPage = page;
  }

  ngOnDestroy(): void {
    this.subscribe$.forEach(sub => sub.unsubscribe());
  }
}

card.component

import { Component, OnInit, Input } from '@angular/core';
import { Router } from '@angular/router';
import { AuthService } from 'src/app/core/services/auth.service';
import { Product } from 'src/app/models/product.model';
import { CartProductModel } from 'src/app/core/models/cart/cart.model';
import { Store } from '@ngrx/store';
import { AppState } from 'src/app/core/store/app.state';
import { AddToCart } from 'src/app/core/store/cart/cart.actions';
@Component({
  selector: 'app-card',
  templateUrl: './card.component.html',
  styleUrls: ['./card.component.scss']
})
export class CardComponent implements OnInit {
  @Input() product: Product;

  isAdmin: boolean = false;
  isInCart: boolean;
  route: Router;
  constructor(
    private authService: AuthService,
    private router: Router,
    private store: Store<AppState>
  ) {}

  ngDoCheck() {
    this.isAdmin = this.authService.getIsAdmin();
  }

  addToCart() {
    if (!this.authService.isAuth()) {
      this.router.navigate(['/']);
      return;
    }

    const productToAdd = new CartProductModel(
      this.product._id,
      this.product.name,
      this.product.image,
      this.product.price,
      1
    );

    console.log(productToAdd);
    this.store.dispatch(new AddToCart(productToAdd));
  }
  ngOnInit() {}
}
javascript angular typescript ngrx
1个回答
0
投票

问题是,在productReducer函数中,default中的switch case返回initialState而不是返回state

© www.soinside.com 2019 - 2024. All rights reserved.