Skip to content

Instantly share code, notes, and snippets.

@perjerz
Last active June 29, 2018 16:33
Show Gist options
  • Save perjerz/ff6c98aabce25c192cc462d84c74ccb5 to your computer and use it in GitHub Desktop.
Save perjerz/ff6c98aabce25c192cc462d84c74ccb5 to your computer and use it in GitHub Desktop.
NgRx Blog
import { Item } from './cart.interfaces';
export const EXAMPLE_ACTION = 'EXAMPLE_ACTION';
export const ADD_ITEM_TO_CART = 'ADD_ITEM_TO_CART';
export const LIST_ITEMS = 'LIST_ITEMS';
export const ITEMS_LISTED = 'ITEMS_LISTED';
export const UPDATE_ITEM_AMOUNT = 'UPDATE_ITEMS_AMOUNT';
export const ITEM_AMOUNT_UPDATED = 'ITEM_AMOUNT_UPDATED';
export const REMOVE_ITEM = 'REMOVE_ITEM';
export class ExampleAction {
// ประกาศ attribute type สำหรับระบุว่าเป็น Action อะไร ใน Reducer
readonly type = EXAMPLE_ACTION;
// payload คือของที่จะส่งเข้าไปกับ Action ซึ่งก็คือ Item นั้นและจำนวน จะมัดรวมเป็น Object ก้อนเดียวก็ได้ แต่ผู้เขียนชอบแยกกัน
}
// Action ดึงข้อมูล Item ทั้งหมดจาก API (Side Effect)
export class ListItems {
readonly type = LIST_ITEMS;
constructor() {}
}
// Action รับข้อมูลที่ได้จาก API (Update State)
export class ItemsListed {
readonly type = ITEMS_LISTED;
constructor(public items: Item[]) {}
}
// Action User เพิ่มสินค้าเข้ารถเข็นผ่าน API (Side Effect)
export class AddItemToCart {
readonly type = ADD_ITEM_TO_CART;
constructor(public item: Item, public amount: number) {}
}
// Action User แก้ไขจำนวนสินค้าในรถเข็น ยิงไปที่ API (Side Effect)
export class UpdateItemAmount {
readonly type = UPDATE_ITEM_AMOUNT;
constructor(public id: string, public amount: number) {}
}
// Action อัพเดท State ของ Item Amount ใน App (Reducer)
export class ItemAmountUpdated {
readonly type = ITEM_AMOUNT_UPDATED;
constructor(public id: string, public amount: number) {}
}
// Action User เอาสินค้าออกจากรถเข็น ยิงไปที่ API (Side Effect)
export class RemoveItems {
readonly type = REMOVE_ITEM;
constructor(public id: string) {}
}
// Action User อัพเดท State เอา Item ออกด้วย id ใน App (Reducer)
export class ItemsRemoved {
readonly type = REMOVE_ITEM;
constructor(public id: string) {}
}
// Action User จ่ายเงิน ยิง Api หลังบ้านตัดเงิน
export class CheckOut {
constructor() {}
}
export type CartAction =
| ExampleAction
| AddItemToCart
| ListItems
| ItemsListed
| UpdateItemAmount
| ItemAmountUpdated
| RemoveItems
| ItemsRemoved
| CheckOut;
import { CartState } from './cart.interfaces';
import { ADD_ITEM_TO_CART, LIST_ITEMS, ItemToCartAdded, AddItemToCart } from './cart.actions';
@Injectable()
export class CartEffects {
// Decorator ระบุว่าคือ Effect และสามารถตั้งค่าว่าาจะ Dispatch Action กลับไปหรือไม่
@Effect(/*{dispatch: false}*/) // สามารถตั้งได้ว่าไม่ dispatch action
addItemToCart$ = this.actions$.pipe(
// สนใจแค่สายข้อมูล Action ของ Add Item To Cart
.ofType(ADD_ITEM_TO_CART),
switchMap((action: AddItemToCart) =>
this.http.post('/item', {id: action.id, amount: action.amount})
.pipe(
map(item => new ItemToCartAdded(item.id, item.amount)), // dispatch Action เพื่ออัพเดท item id, amount ไปที่ reducer
catchBackendError(err => console.error(err))
)
)
);
@Effect()
listItems$ = this.actions$.pipe(
// สนใจแค่สายข้อมูล Action ของ List Items
.ofType(LIST_ITEMS),
switchMap(() => this.http.get('/items').pipe(
map(item => new ItemsListed(item)), // dispatch Action เพื่ออัพเดท displayItems ทั้งหมด
catchBackendError(err => console.error(err))
)
)
);
constructor(
private http: HttpClient,
private store: Store<CartState>,
private actions$: Actions
) {}
}
export interface Item {
id: string;
name: string;
type: string;
price: string;
description: string;
}
import { Cart } from './cart.interfaces';
import {
CartAction,
ITEM_TO_CART_ADDED,
ITEMS_LISTED,
ITEM_AMOUNT_UPDATED,
ITEMS_REMOVED
} from './cart.actions';
import { initialState } from './cart.init';
export function cartReducer(state = initialState, action: CartAction): Cart {
switch (action.type) {
case ITEM_TO_CART_ADDED:
case ITEM_AMOUNT_UPDATED: {
return { ...state, selectedItems: { ...state.selectedItems, [action.id]: action.amount } };
}
case ITEMS_LISTED: {
return { ...state, displayItems: action.items };
}
case ITEMS_REMOVED: {
const { [action.id]: omitItem, ...otherItems } = state.selectedItems;
return { ...state, selectedItems: otherItems };
}
default:
return state;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment