面试题答案
一键面试在这种包含复杂交互逻辑的电商购物车功能场景下,优先选择 useReducer
。
理由
- 逻辑清晰:
useReducer
更适合管理包含多个子逻辑的复杂状态。对于购物车功能,添加、删除、修改数量等操作逻辑相对复杂,使用useReducer
可以将这些操作集中在一个reducer
函数中处理,使得代码结构更加清晰,易于维护。例如,在reducer
函数中可以针对不同的 action 类型(如ADD_ITEM
、REMOVE_ITEM
、UPDATE_QUANTITY
等)进行不同的状态更新逻辑处理。 - 可追溯性:
useReducer
的action
机制提供了更好的可追溯性。每个状态变化都是由一个明确的action
触发,方便进行调试和状态跟踪。当出现问题时,可以很容易地找到是哪个action
导致了状态的错误变化。 - 性能优化:在某些情况下,
useReducer
可以通过减少不必要的重新渲染来优化性能。例如,可以使用React.memo
与useReducer
结合,在action
没有改变依赖值时,避免组件的不必要重新渲染。
状态管理实现
- 定义状态结构:
// 定义购物车商品项的类型
type CartItem = {
id: string;
name: string;
price: number;
quantity: number;
};
// 定义购物车状态类型
type CartState = {
items: CartItem[];
totalPrice: number;
};
- 定义
action
类型:
// 定义 action 类型
type CartAction =
| { type: 'ADD_ITEM'; payload: CartItem }
| { type: 'REMOVE_ITEM'; payload: string }
| { type: 'UPDATE_QUANTITY'; payload: { id: string; quantity: number } };
- 编写
reducer
函数:
const cartReducer = (state: CartState, action: CartAction): CartState => {
switch (action.type) {
case 'ADD_ITEM':
return {
...state,
items: [...state.items, action.payload],
totalPrice: state.totalPrice + action.payload.price * action.payload.quantity
};
case 'REMOVE_ITEM':
const removedItem = state.items.find(item => item.id === action.payload);
if (!removedItem) return state;
return {
...state,
items: state.items.filter(item => item.id!== action.payload),
totalPrice: state.totalPrice - removedItem.price * removedItem.quantity
};
case 'UPDATE_QUANTITY':
return state.items.map(item => {
if (item.id === action.payload.id) {
const priceDiff = (action.payload.quantity - item.quantity) * item.price;
return {...item, quantity: action.payload.quantity };
}
return item;
});
return {
...state,
totalPrice: state.totalPrice + priceDiff
};
default:
return state;
}
};
- 在组件中使用
useReducer
:
import React, { useReducer } from'react';
const Cart: React.FC = () => {
const initialState: CartState = {
items: [],
totalPrice: 0
};
const [cart, dispatch] = useReducer(cartReducer, initialState);
const addItem = (item: CartItem) => {
dispatch({ type: 'ADD_ITEM', payload: item });
};
const removeItem = (id: string) => {
dispatch({ type: 'REMOVE_ITEM', payload: id });
};
const updateQuantity = (id: string, quantity: number) => {
dispatch({ type: 'UPDATE_QUANTITY', payload: { id, quantity } });
};
return (
<div>
{/* 购物车组件内容 */}
</div>
);
};
export default Cart;