使用useReducer比useState更合适的原因
- 状态管理复杂性:当购物车商品数量、价格等状态涉及复杂计算和更新逻辑时,
useReducer
将所有更新逻辑集中在一个reducer
函数中,相比useState
分散的状态更新逻辑,更易于维护和理解。
- 可追溯性:
reducer
函数接收前一个状态和一个动作对象,动作对象可以清晰描述状态变化的意图,方便追踪状态变化过程,而useState
在复杂逻辑下状态变化较难追踪。
- 代码结构:
useReducer
有助于将组件逻辑和状态更新逻辑分离,使组件代码结构更清晰,特别是在购物车这样状态变化复杂的场景。
实现代码示例
import React, { useReducer } from 'react';
// 定义初始状态
const initialState = {
items: [],
totalPrice: 0,
totalQuantity: 0
};
// 定义reducer函数
const cartReducer = (state, action) => {
switch (action.type) {
case 'ADD_ITEM':
const newItem = action.payload;
const existingItemIndex = state.items.findIndex(item => item.id === newItem.id);
let updatedItems;
let updatedTotalQuantity;
let updatedTotalPrice;
if (existingItemIndex >= 0) {
const existingItem = state.items[existingItemIndex];
updatedItems = [...state.items];
updatedItems[existingItemIndex] = {
...existingItem,
quantity: existingItem.quantity + newItem.quantity
};
updatedTotalQuantity = state.totalQuantity + newItem.quantity;
updatedTotalPrice = state.totalPrice + newItem.price * newItem.quantity;
} else {
updatedItems = [...state.items, {...newItem }];
updatedTotalQuantity = state.totalQuantity + newItem.quantity;
updatedTotalPrice = state.totalPrice + newItem.price * newItem.quantity;
}
return {
items: updatedItems,
totalPrice: updatedTotalPrice,
totalQuantity: updatedTotalQuantity
};
case 'REMOVE_ITEM':
const itemToRemove = action.payload;
const itemIndex = state.items.findIndex(item => item.id === itemToRemove.id);
const itemToDelete = state.items[itemIndex];
let newTotalQuantity = state.totalQuantity - itemToDelete.quantity;
let newTotalPrice = state.totalPrice - itemToDelete.price * itemToDelete.quantity;
let newItems;
if (itemToDelete.quantity > 1) {
newItems = [...state.items];
newItems[itemIndex] = {
...itemToDelete,
quantity: itemToDelete.quantity - 1
};
} else {
newItems = state.items.filter(item => item.id !== itemToRemove.id);
}
return {
items: newItems,
totalPrice: newTotalPrice,
totalQuantity: newTotalQuantity
};
default:
return state;
}
};
const ShoppingCart = () => {
const [cartState, dispatch] = useReducer(cartReducer, initialState);
const addItemToCart = (item) => {
dispatch({ type: 'ADD_ITEM', payload: item });
};
const removeItemFromCart = (item) => {
dispatch({ type: 'REMOVE_ITEM', payload: item });
};
return (
<div>
<h1>Shopping Cart</h1>
<ul>
{cartState.items.map(item => (
<li key={item.id}>
{item.name} - Quantity: {item.quantity} - Price: {item.price * item.quantity}
<button onClick={() => removeItemFromCart(item)}>Remove</button>
</li>
))}
</ul>
<p>Total Quantity: {cartState.totalQuantity}</p>
<p>Total Price: {cartState.totalPrice}</p>
<button onClick={() => addItemToCart({ id: 1, name: 'Sample Product', quantity: 1, price: 10 })}>Add Item</button>
</div>
);
};
export default ShoppingCart;