吖昭的技术笔记
跟着吖昭写笔记,从 0 到 1 的技术成长看得见
文章48浏览1975本站已运行7723

《React Hooks 实战:购物车功能实现》:详解 useState、useEffect 等钩子在实际项目中的应用,附性能优化技巧。

《React Hooks 实战:购物车功能实现》
购物车是电商应用的核心模块,涉及商品添加、数量修改、选中状态切换、总价计算等复杂交互。React Hooks 的出现彻底改变了函数组件的能力,让我们无需编写类组件就能管理状态和副作用。以下通过实现一个完整的购物车功能,详useState「状态管理」、useEffect「副作用处理」、useMemo「性能优化」等钩子的实战用法。
一、基础架构:用 useState 管理购物车状态
购物车的核心状态包括「商品列表」「选中状态」「数量」等,useState是管理这些状态的基础工具。我们先从初始化购物车数据开始构建功能。
1. 状态设计与初始化

设计思路
  • 将商品列表设计为数组对象,每个对象包含独立属性,便于单独操作某件商品。
  • 全选状态与商品选中状态是「联动关系」,需单独声明状态而非从商品列表中计算,避免逻辑冗余。
2. 核心交互:基于 useState 的状态更新
(1)修改商品数量

(2)切换商品选中状态

(3)全选 / 取消全选

关键原则
  • 状态更新必须通setXxx函数,禁止直接修prevItems(React 依赖新对象 / 数组触发重新渲染)。
  • 复杂状态更新推荐使用「函数式更新」(prev => new),避免因状态依赖导致的更新异常。
二、副作用处理:用 useEffect 同步数据与交互
购物车需要处理「本地存储持久化」「总价计算联动」等副作用逻辑,useEffect是连接状态与副作用的桥梁。
1. 购物车数据持久化
刷新页面后保留购物车数据,需将状态同步localStorage

执行时机
  • 第一useEffect:组件挂载后 +cartItems更新时执行,确保本地存储与状态一致。
  • 第二useEffect:仅挂载时执行,优先读取本地数据初始化状态。
2. 全选状态联动
当所有商品都被选中时,自动勾选全选框;反之取消:

防坑点
  • 若省selectAll依赖,当手动点击全选框时,可能因状态不一致导致逻辑错误。
  • allChecked !== selectAll判断,避免不必要的状态更新(优化性能)。
三、性能优化:用 useMemo 与 useCallback 减少重渲染
当购物车商品数量较多时,频繁的状态更新可能导致组件重复渲染。通过「缓存计算结果」和「稳定函数引用」可显著提升性能。
1. 用 useMemo 缓存计算结果
总价计算是典型的「纯计算逻辑」,可缓存结果避免每次渲染重复计算:

适用场景
  • 复杂的数组过滤 / 排序 / 计算(如总价、折扣价)。
  • 返回值用于渲染(避免因计算耗时导致的渲染卡顿)。
2. 用 useCallback 稳定函数引用
传递给子组件的回调函数若每次渲染都重新创建,会导致子组件不必要的重渲染:

优化原理
  • 未使useCallback时,每ShoppingCart渲染都会创建新handleRemoveItem函数。
  • 子组CartItem若使React.memo优化,会onRemove引用变化而重新渲染,useCallback可避免这一问题。
四、完整组件:购物车功能整合
结合上述钩子,实现一个包含「增删商品、修改数量、选中切换、持久化」的完整购物车:

const ShoppingCart = () => {
// 1. 状态管理
const [cartItems, setCartItems] = useState([]);
const [selectAll, setSelectAll] = useState(false);
// 2. 副作用:初始化与持久化
useEffect(() => {
const saved = localStorage.getItem('cartData');
if (saved) setCartItems(JSON.parse(saved));
}, []);
useEffect(() => {
localStorage.setItem('cartData', JSON.stringify(cartItems));
}, [cartItems]);
// 3. 全选联动
useEffect(() => {
const allChecked = cartItems.length > 0 && cartItems.every(i => i.checked);
if (allChecked !== selectAll) setSelectAll(allChecked);
}, [cartItems, selectAll]);
// 4. 缓存回调函数
const handleRemove = useCallback((id) => {
setCartItems(prev => prev.filter(i => i.id !== id));
}, []);

总结:Hooks 实战核心要点
  1. 状态设计:拆分细粒度状态(cartItemsselectAll),避免状态嵌套过深导致更新复杂。
  1. 副作用依赖useEffect的依赖数组必须完整(遗漏依赖可能导致数据不一致),可通过 ESLint 插eslint-plugin-react-hooks自动检测。
  1. 性能优化时机
  • 当组件渲染频率高且计算复杂时,使useMemo缓存结果。
  • 当传递给子组件的回调函数导致不必要重渲染时,useCallback稳定引用。
通过购物车案例可见,Hooks 不仅简化了状态管理代码,更让组件逻辑清晰可复用。在实际项目中,还可结useReducer(复杂状态逻辑)、useContext(跨组件状态共享)进一步扩展功能,构建更健壮的 React 应用。
上一篇:
下一篇:

相关推荐

你必须 登录 才能发表评论.

隐藏边栏