Come creare un carrello della spesa in Next.js con Context e useReducer

Come creare un carrello della spesa in Next.js con Context e useReducer

Un carrello della spesa è una parte essenziale di qualsiasi sito di e-commerce. Consente ai clienti di conservare e acquistare prodotti.

In un’app di e-commerce Next.js, puoi utilizzare l’API Context e l’hook useReducer per creare un carrello. L’API di contesto semplifica la condivisione dei dati del carrello tra i componenti mentre useReducer gestisce lo stato del carrello.

Creazione della pagina del prodotto

Nella cartella delle pagine, crea un nuovo file chiamato Product.jsx che esegue il rendering di un singolo prodotto.

export default function Product({id, name, price}) {
  return (
    <div>
      <p>{name}</p>
      <p>{price}</p>
      <button>Add to Cart</button>
    </div>
  )
}

Il componente del prodotto accetta l’ID, il nome e il prezzo di un prodotto e lo visualizza. Ha anche un pulsante “Aggiungi al carrello”.

Quando un prodotto è già stato aggiunto al carrello, il pulsante dovrebbe passare a un pulsante “rimuovi dal carrello” e se un prodotto non è nel carrello, la pagina dovrebbe visualizzare il pulsante “Aggiungi al carrello”.

Per implementare questa funzionalità, dovrai tenere traccia degli articoli nel carrello utilizzando l’API di contesto e l’hook useReducer.

Creazione di un carrello degli acquisti utilizzando l’API Context

L’API di contesto ti consente di condividere i dati tra diversi componenti senza dover passare oggetti di scena manualmente da genitore a figlio. Questi componenti possono essere la barra di navigazione, la pagina dei dettagli del prodotto o la pagina di pagamento.

Crea un nuovo file chiamato cartContext.js in una cartella chiamata contesto e crea il contesto.

import { createContext } from "react";

export const CartContext = createContext({
    items: [],
});

CartContext accetta una matrice di elementi come valore predefinito.

Successivamente, crea il provider di contesto. Un provider di contesto consente ai componenti che utilizzano il contesto di sottoscrivere le modifiche di contesto.

In una nuova funzione chiamata cartProvider, aggiungi quanto segue:

export const CartProvider = ({ children }) => {
  return <CartContext.Provider>{children}</CartContext.Provider>;
};

Per tenere traccia degli articoli nel carrello, utilizzerai l’hook useReducer.

L’hook useReducer funziona come l’hook useState, tranne per il fatto che aiuta a gestire una logica di stato più complessa. Accetta una funzione di riduzione e lo stato iniziale. Restituisce lo stato corrente e una funzione dispatch che passa un’azione alla funzione reducer.

Crea una nuova funzione chiamata CartReducer e aggiungi il riduttore.

const cartReducer = (state, action) => {
  const { type, payload } = action;

  switch (type) {
    case "ADD":
      return {
        ...state,
        items: payload.items,
      };

    case "REMOVE":
      return {
        ...state,
        items: payload.items,
      };

    default:
      throw new Error("No case for that type");
  }
};

La funzione reducer comprende un’istruzione switch che aggiorna lo stato in base al tipo di azione. La funzione di riduzione del carrello ha azioni “AGGIUNGI” e “RIMUOVI” che aggiungono rispettivamente al carrello e rimuovono dal carrello.

Dopo aver creato la funzione reducer, usala nell’hook useReducer. Inizia creando la funzione CartProvider. Questa è la funzione che fornirà il contesto ad altri componenti.

export const CartProvider = ({children}) => {
  return <CartContext.Provider>{children}</CartContext.Provider>;
}

Quindi, crea l’hook useReducer.

export const CartProvider = ({ children }) => {
  const [state, dispatch] = useReducer(cartReducer, { items: [] });
  return <CartContext.Provider>{children}</CartContext.Provider>;
};

La funzione dispatch è responsabile dell’aggiornamento dello stato del carrello, quindi modifica la funzione CartProvider per includere le funzioni che inviano i prodotti all’hook useReducer quando il carrello si aggiorna.

import { createContext, useReducer } from "react";

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

  const addToCart = (product) => {
    const updatedCart = [...state.items, product];

    dispatch({
      type: "ADD",
      payload: {
        items: updatedCart,
      },
    });
  };

  const removeFromCart = (id) => {
    const updatedCart = state.items.filter(
      (currentProduct) => currentProduct.id! == id
    );

    dispatch({
      type: "REMOVE",
      payload: {
        items: updatedCart,
      },
    });
  };

  return <CartContext.Provider>{children}</CartContext.Provider>;
};

La funzione addToCart aggiunge il nuovo prodotto ai prodotti esistenti e restituisce i prodotti aggiornati nell’oggetto payload della funzione dispatch. Analogamente, la funzione removeFromCart filtra l’elemento in base all’ID e restituisce l’elenco aggiornato.

È inoltre necessario restituire il valore prop nel provider CartContext.

export const CartProvider = ({ children }) => {
  const [state, dispatch] = useReducer(cartReducer, {
    items: [],
  });

  const addToCart = (product) => {};
  const removeFromCart = (id) => {};

  const value = {
    items: state.items,
    addToCart,
    removeFromCart,
  };

  return <CartContext.Provider value={value}>{children}</CartContext.Provider>;
}

Il valore prop viene consumato tramite l’hook useContext.

Consumare il contesto del carrello

Finora hai creato il contesto del carrello e creato una funzione useReducer che aggiorna il carrello. Successivamente, utilizzerai il contesto del carrello nel componente del prodotto utilizzando l’hook useContext.

Inizia avvolgendo index.js, il componente principale, con il provider di contesto per rendere disponibili i valori di contesto nell’intera applicazione.

import { CartProvider } from "../context/cartContext";

function MyApp({ Component, pageProps }) {
  return (
    <CartProvider>
      <Component {...pageProps} />
    </CartProvider>
  );
}


export default MyApp;

Quindi importare l’hook useContext e il fornitore del contesto del carrello in Product.js

import { useContext } from "react"
import { CartContext } from "../context/cartContext"

export default function Product() {
  const {items, addToCart, removeFromCart} = useContext(CartContext)


  return (
    <>
      <div>
        <p>{name}</p>
        <p>{price}</p>
        <button>Add to Cart</button>
      </div>
    </>
  )
}

La funzione del pulsante dipende dal fatto che l’articolo sia già nel carrello. Se un articolo esiste nel carrello, il pulsante dovrebbe rimuoverlo dal carrello e se un articolo non è già nel carrello, dovrebbe aggiungerlo. Ciò significa che devi tenere traccia dello stato dell’elemento utilizzando useEffect e useState. Il codice useEffect controlla se l’articolo è nel carrello dopo il rendering del componente mentre useState aggiorna lo stato dell’articolo.

const [exists, setExists] = useState(false);

useEffect(() => {
  const inCart = items.find((item) => item.id === id);


  if (inCart) {
      setExists(true);
  } else {
      setExists(false);
  }
}, [items, id]);

Ora, usa il rendering condizionale per mostrare il pulsante in base allo stato esistente.

return (
  <div>
    <p>{name}</p>
    <p>{price}</p>
    {
     exists
     ? <button onClick={() => removeFromCart(id)}>Remove from Cart</button>
     : <button onClick={() => addToCart({id, name, price})}>Add to Cart</button>
   }
  </div>
)

Si noti che le funzioni del gestore onClick sono le funzioni removeFromCart e addToCart definite nel provider di contesto.

Aggiunta di più funzionalità al carrello

Hai imparato a creare un carrello della spesa utilizzando l’API di contesto e l’hook useReducer.

Anche se questa guida tratta solo funzionalità di aggiunta e rimozione, puoi utilizzare gli stessi concetti per aggiungere più funzionalità come la regolazione delle quantità di articoli nel carrello. La cosa cruciale è comprendere l’API di contesto e come utilizzare gli hook per aggiornare i dettagli del carrello.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *