首頁 > web前端 > js教程 > React 中使用 useContext 和 useReducer 進行狀態管理:建立全域購物車

React 中使用 useContext 和 useReducer 進行狀態管理:建立全域購物車

Linda Hamilton
發布: 2024-11-11 14:38:02
原創
919 人瀏覽過

State Management with useContext and useReducer in React: Building a Global Shopping Cart

React 中使用 useContext 和 useReducer 進行進階狀態管理:建立全域購物車

在上一篇文章中,我們介紹了結合 useContext 和 useReducer 在 React 應用程式中有效管理全域狀態的概念。我們透過建立一個簡單的待辦事項清單來示範這一點。現在,我們將更進一步,將這些概念應用到一個更複雜的現實範例中——全球購物車。

本指南將介紹如何管理多個狀態和操作,例如新增、更新和刪除項目以及計算總數,同時保持應用程式的可擴展性和效能。

在第二部分中,您將學習:

  1. 使用 useReducer 處理較複雜的狀態
  2. 建立靈活的上下文提供者以全域管理狀態和操作。
  3. 實現高階減速器函數來執行計算並處理各種類型的操作。
  4. 最佳化組件表現透過記憶來獲得更好的表現。

讓我們開始吧!


項目概要:全球購物車

我們的購物車應用程式將具有:

  • 產品清單:一組可加入購物車的商品。
  • 購物車功能:使用者可以新增、更新和刪除購物車中的商品。
  • 購物車總計:計算並顯示商品總數和總價。

我們將從設定上下文和減速器開始,然後建立組件來展示功能。

設定和初始文件

首先,初始化您的 React 專案並設定基本資料夾結構:

src/
├── CartContext.js
├── CartProvider.js
├── ProductList.js
├── Cart.js
└── App.js
登入後複製
登入後複製

步驟一:建立初始狀態和Reducer

我們將從代表空購物車和一組範例產品的初始狀態開始。

初始狀態:

// Initial state structure
const initialState = {
  products: [
    { id: 1, name: "Product A", price: 30 },
    { id: 2, name: "Product B", price: 20 },
    { id: 3, name: "Product C", price: 50 }
  ],
  cart: [],
  totalItems: 0,
  totalPrice: 0
};
登入後複製
登入後複製

減速器功能:

我們將設定一個 cartReducer 函數來處理各種操作,例如新增商品、更新商品數量、刪除商品和計算總計。

src/
├── CartContext.js
├── CartProvider.js
├── ProductList.js
├── Cart.js
└── App.js
登入後複製
登入後複製

解釋

  • ADD_TO_CART:將商品加入購物車,如果已存在則增加數量。
  • REMOVE_FROM_CART:根據 ID 刪除項目。
  • UPDATE_QUANTITY:更新購物車中商品的數量。
  • CALCULATE_TOTALS:計算購物車中的商品總數和總價。

第 2 步:建立上下文和提供者

現在,我們將建立一個上下文和提供者來全域傳遞我們的狀態和調度函數。這將允許所有組件存取購物車狀態和操作。

CartContext.js

// Initial state structure
const initialState = {
  products: [
    { id: 1, name: "Product A", price: 30 },
    { id: 2, name: "Product B", price: 20 },
    { id: 3, name: "Product C", price: 50 }
  ],
  cart: [],
  totalItems: 0,
  totalPrice: 0
};
登入後複製
登入後複製

第 3 步:建構元件

設定了提供者和上下文後,我們現在可以為 產品清單購物車建立元件。


產品清單組件

ProductList 元件將顯示可用產品列表,並允許使用者將產品新增至購物車。

ProductList.js

function cartReducer(state, action) {
  switch (action.type) {
    case "ADD_TO_CART": {
      const item = state.cart.find(item => item.id === action.payload.id);
      const updatedCart = item
        ? state.cart.map(cartItem =>
            cartItem.id === item.id
              ? { ...cartItem, quantity: cartItem.quantity + 1 }
              : cartItem
          )
        : [...state.cart, { ...action.payload, quantity: 1 }];

      return { ...state, cart: updatedCart };
    }

    case "REMOVE_FROM_CART": {
      const updatedCart = state.cart.filter(item => item.id !== action.payload);
      return { ...state, cart: updatedCart };
    }

    case "UPDATE_QUANTITY": {
      const updatedCart = state.cart.map(item =>
        item.id === action.payload.id
          ? { ...item, quantity: action.payload.quantity }
          : item
      );
      return { ...state, cart: updatedCart };
    }

    case "CALCULATE_TOTALS": {
      const { totalItems, totalPrice } = state.cart.reduce(
        (totals, item) => {
          totals.totalItems += item.quantity;
          totals.totalPrice += item.price * item.quantity;
          return totals;
        },
        { totalItems: 0, totalPrice: 0 }
      );
      return { ...state, totalItems, totalPrice };
    }

    default:
      return state;
  }
}
登入後複製

購物車組件

購物車組件顯示購物車中的商品,允許更新數量、刪除商品,並顯示商品總數和價格。

Cart.js

import React, { createContext, useReducer } from 'react';

export const CartContext = createContext();

export function CartProvider({ children }) {
  const [state, dispatch] = useReducer(cartReducer, initialState);

  return (
    <CartContext.Provider value={{ state, dispatch }}>
      {children}
    </CartContext.Provider>
  );
}
登入後複製

解釋

  • handleRemove:從購物車移除商品。
  • handleUpdateQuantity:更新所選商品的數量。
  • 商品總數和價格:購物車組件根據狀態中的計算值顯示商品總數和價格。

第 4 步:使用 Provider 包裝應用程式

為了確保所有組件都可以存取購物車狀態,請將整個應用程式包裝在 CartProvider 中。

App.js

import React, { useContext } from 'react';
import { CartContext } from './CartContext';

function ProductList() {
  const { state, dispatch } = useContext(CartContext);

  const handleAddToCart = (product) => {
    dispatch({ type: "ADD_TO_CART", payload: product });
    dispatch({ type: "CALCULATE_TOTALS" });
  };

  return (
    <div>
      <h2>Products</h2>
      <ul>
        {state.products.map(product => (
          <li key={product.id}>
            {product.name} - ${product.price}
            <button onClick={() => handleAddToCart(product)}>Add to Cart</button>
          </li>
        ))}
      </ul>
    </div>
  );
}

export default ProductList;
登入後複製

最後的處理:記憶與最佳化

隨著應用程式的成長,優化效能至關重要。這裡有一些提示:

  1. Memoize Components:使用 React.memo 來防止依賴狀態的元件不必要的重新渲染。
  2. 單獨的上下文:如果產品和購物車上下文變得太大,請考慮將它們分開,以允許更有針對性的狀態更新。

回顧與結論

在本進階指南中,我們使用 useContext 和 useReducer 來管理全域購物車。主要要點包括:

  1. 複雜的狀態管理:useReducer 簡化了管理複雜的操作和計算。
  2. 使用 useContext 的全域狀態:使狀態可以跨組件樹存取。
  3. 可擴充模式:在上下文中分離狀態和操作可以實現更清晰、更模組化的程式碼。

嘗試將此方法應用於您的項目,看看它如何提高應用程式的可擴展性和效能。快樂編碼! ?

以上是React 中使用 useContext 和 useReducer 進行狀態管理:建立全域購物車的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板