Zmiana stanu koszyka po dodaniu nowego produktu

0

Cześć,

tworzę sobie appkę w React przy użyciu TypeScript i mianowicie zastanawiam się jak najprościej zmienic stan pomiędzy komponentami. Przedmioty w zakładce Store są trzymane jako oddzielne komponenty StoreItem i one zawierają poszczególne dane o produkcje jak nazwa, opis, cena etc. oraz przycisk dodawania do koszyka. Sam koszyk oraz wyświetlana ilość elementów w koszyku póki co jest wpisana z palca jako statyczna wartość i znajduje się w komponencie Navbar.

Link do projektu: https://github.com/goldipl/React_Shop_App

Prośba o pomoc/nakierunkowanie, jakie będzie najlepsze rozwiązanie. Trzeba po prostu użyć useContext?

1

Jeśli będziesz potrzebował tego w kilku komponentach to tak, może być context.

Przy najprostszym sposobie wygląda to tak:

1) Tworzysz sobie context w osobnym pliku

import { createContext, useState } from 'react';

export const ShopContext = createContext();

export const ShopProvider = () => {
  const [products, setProducts] = useState([]); // lista produktów
  const [costs, setCosts] = useState(0); // finalna cena do zapłaty
  // Jakieś inne wartości, które chcesz udostępnić

  return (
    <ShopContext.Provider value={{
      products,
      setProducts,
      costs,
      setCosts,
    }}>
      {children}
    </ShopContext.Provider>
  );
}

2) Importujesz go w komponencie App

// ...
import { ShopContextProvider } from '...';

const App = () => (
 <ShopContextProvider>
   <Navbar />
    <Routes>
      <Route path="/React_Shop_App/" element={<Home />} />
      <Route path="/React_Shop_App/store" element={<Store />} />
      <Route path="/React_Shop_App/about" element={<About />} />
    </Routes>
   <Footer />
 </ShopContextProvider>
)

3) Pobierasz wartość przez useContext

// ...
import { ShopContext } from '...';

const StoreItem = (...) => {
  const data = useContext(ShopContext);

  // ...
}
0
Xarviel napisał(a):

Jeśli będziesz potrzebował tego w kilku komponentach to tak, może być context.

Przy najprostszym sposobie wygląda to tak:

1) Tworzysz sobie context w osobnym pliku

import { createContext, useState } from 'react';

export const ShopContext = createContext();

export const ShopProvider = () => {
  const [products, setProducts] = useState([]); // lista produktów
  const [costs, setCosts] = useState(0); // finalna cena do zapłaty
  // Jakieś inne wartości, które chcesz udostępnić

  return (
    <ShopContext.Provider value={{
      products,
      setProducts,
      costs,
      setCosts,
    }}>
      {children}
    </ShopContext.Provider>
  );
}

2) Importujesz go w komponencie App

// ...
import { ShopContextProvider } from '...';

const App = () => (
 <ShopContextProvider>
   <Navbar />
    <Routes>
      <Route path="/React_Shop_App/" element={<Home />} />
      <Route path="/React_Shop_App/store" element={<Store />} />
      <Route path="/React_Shop_App/about" element={<About />} />
    </Routes>
   <Footer />
 </ShopContextProvider>
)

3) Pobierasz wartość przez useContext

// ...
import { ShopContext } from '...';

const StoreItem = (...) => {
  const data = useContext(ShopContext);

  // ...
}

@Xarviel: Chyba się zaciąłem, co prawda zrobiłem context ze stanem ilości produktów, zaimportowałem context w App to za bardzo nie ogarniam jeszcze jak to powiązać z moją wartością countera w StoreItem. Tak aby rzeczywiście klkniecie przycisku dodaj do koszyka zmieniała cyfrę przy koszyku w navbarze...

1
darkonepl napisał(a):

@Xarviel: Chyba się zaciąłem, co prawda zrobiłem context ze stanem ilości produktów, zaimportowałem context w App to za bardzo nie ogarniam jeszcze jak to powiązać z moją wartością countera w StoreItem. Tak aby rzeczywiście klkniecie przycisku dodaj do koszyka zmieniała cyfrę przy koszyku w navbarze...

Napiszę Ci kod dotyczący samego contextu, pomijając pozostałe fragmenty, które już masz do tej pory


https://github.com/goldipl/React_Shop_App/blob/master/src/context/ShopContextProvider.tsx

Jak dobrze rozumiem, ta zmienna productsQuantity jest to licznik wszystkich produktów jakie użytkownik wybierze do swojego koszyka?
Wybiera przykładowo 2 mleka, płatki kukurydziane, chleb, ryż, mięso, czyli 6 rzeczy i licznik ma wskazywać te 6 rzeczy, które wybrał.

Bo jakbyś chciał rozróżnić dokładnie co kupił itd z podziałem jak na paragonie to sama wartość prymitywna się nie nadaje i musiałby być przykładowo obiekt

const [productsQuantity, setProductsQuantity] = useState({});

/*

setProductsQuantity({
  "milk": 2,
  "meat": 1,
  "rice": 1,
  "cornflakes": 1,
  "bread", 1
});

*/

ale załóżmy, że jest to nadal liczba tak jak u Ciebie i nic tutaj nie zmieniamy


https://github.com/goldipl/React_Shop_App/blob/master/src/components/Navbar.tsx

Samo wyświetlenie jest dość proste, wystarczy zaimportować context i użyć hooka useContext do pobrania wartości

import { useContext } from 'react';
import { ShopContext } from '../context/ShopContextProvider';

const ResponsiveAppBar = () => {
 = () => {
  const { productsQuantity } = useContext(ShopContext);

  return (
     <>
       Ilość produktów: {productsQuantity}
     </>
  );
}

https://github.com/goldipl/React_Shop_App/blob/master/src/components/StoreItem.tsx

Tutaj musisz podmienić swój stan counter, na ten pochodzący z contextu, czyli productsQuantity

import { useContext } from 'react';
import { ShopContext } from '../context/ShopContextProvider';

const StoreItem = () => {
  const { productsQuantity, setProductsQuantity } = useContext(ShopContext);

   const counterUp = () => {
    setProductsQuantity(productsQuantity + 1);
  };

  const counterDown = () => {
    setCounter(Math.max(productsQuantity - 1, 0));
  };

  return (
    <>
       <button onClick={counterDown}>
          -
       </button>

       <button onClick={counterUp}>
          +
       </button>
    </>
  );
};
1
Xarviel napisał(a):
darkonepl napisał(a):

[...]

@Xarviel Super, wielkie dzięki :) Miałem jeszcze problem z TypeScriptem w dwóch miejsach z typami, ale otypowałem je jako any i poszło. Aktualnie jeszcze będę musial dopracować, aby każda zmiana tyczyła się pojedyńczego produktu, bo póki co ilość zmienia się we wszystkich StoreItemach/wszystkich produktach jednocześnie, a każdy powinien być osobnym bytem i ewentualnie dodanie do koszyka dopiero po wcisnieciu przycisku dodaj do koszyka.

W sumie miałeś rację, że to nie będzie takie ciężkie, ale jednak praktyka czyni mistrza...:)

1 użytkowników online, w tym zalogowanych: 0, gości: 1