Open drizzle96 opened 3 months ago
// types.ts
export interface CartItem {
name: string;
price: number;
}
export interface CartState { items: CartItem []; total: number; }
export type CartAction = { type: 'ADD_ITEM'; payload: CartItem } | { type: 'REMOVE_ITEM'; payload: number };
```ts
// reducer.ts
import { CartState, CartAction } from './types';
export const cartReducer = (state: CartState, action: CartAction): CartState => {
switch (action.type) {
case 'ADD_ITEM':
return {
...state,
items: [...state.items, action.payload],
total: state.total + action.payload.price,
};
case 'REMOVE_ITEM':
const itemPrice = state.items[action.payload].price;
return {
...state,
items: state.items.filter((_, index) => index !== action.payload),
total: state.total - itemPrice,
};
default:
return state;
}
};
// ShoppingCart.tsx
import React, { useReducer } from 'react';
import { CartState, Item } from './types';
import { cartReducer } from './reducer';
const initialState: CartState = {
items: [],
total: 0,
};
const ShoppingCart: React.FC = () => {
const [state, dispatch] = useReducer(cartReducer, initialState);
const addItem = (item: Item) => {
dispatch({ type: 'ADD_ITEM', payload: item });
};
const removeItem = (index: number) => {
dispatch({ type: 'REMOVE_ITEM', payload: index });
};
return (
<div>
<h1>Shopping Cart</h1>
<ul>
{state.items.map((item, index) => (
<li key={index}>
{item.name} - ${item.price}
<button onClick={() => removeItem(index)}>Remove</button>
</li>
))}
</ul>
<div>Total: ${state.total}</div>
<button onClick={() => addItem({ name: 'Apple', price: 1 })}>Add Apple</button>
</div>
);
};
export default ShoppingCart;
import { Reducer, useReducer } from 'react'
type Item = {
name: string
price: number
}
type State = {
items: Item[]
total: number
}
type Action =
| { type: 'ADD_ITEM', item: Item }
| { type: 'REMOVE_ITEM', index: number }
const reducer: Reducer<State, Action> = (state, action) => {
switch (action.type) {
case 'ADD_ITEM':
return {
...state,
items: [...state.items, action.item],
total: state.total + action.item.price,
}
case 'REMOVE_ITEM':
return {
...state,
items: state.items.filter((_, i) => i !== action.index),
total: state.total - state.items[action.index].price,
}
}
}
const initialState: State = {
items: [],
total: 0,
}
const ShoppingCart = () => {
const [cart, dispatch] = useReducer(reducer, initialState)
return (
<div>
<h1>Shopping Cart</h1>
<ul>
{cart.items.map((item, index) => (
<li key={index}>
{item.name} - ${item.price}
<button onClick={() => dispatch({ type: 'REMOVE_ITEM', index })}>Remove</button>
</li>
))}
</ul>
<div>Total: ${cart.total}</div>
<button onClick={() => dispatch({ type: 'ADD_ITEM', item: { name: 'apple', price: 10000 } })}>Add Apple</button>
</div>
)
}
export default ShoppingCart
❓문제
다음 쇼핑카트 컴포넌트에 타입스크립트를 적용하고 상태 관리로 useReducer를 사용하도록 바꿔주세요!
🎯답변