• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Problem z przekazywaniem stanu - React

Object Storage Arubacloud
0 głosów
113 wizyt
pytanie zadane 10 października 2021 w JavaScript przez Piotr Błaszczak Bywalec (2,890 p.)

Cześć piszę aplikacje sklepu w React i mam problem z wyświetlaniem ilości rzeczy w koszyku tzn. jako globalny stan używam React Context, struktura aplikacji wygląda tak:

import React from 'react';
import { HashRouter as Router } from 'react-router-dom';

import Header from './components/Header/Header.jsx';
import Main from './components/Main/Main.jsx';

import './App.css';

function App() {
  return (
    <Router>
      <Header />
      <Main />
    </Router>
  );
}

export default App;

StoreProvider jest importowany wyżej w Index.js i oplata komponent App, chciałbym uzyskać efekt taki, że ilość rzeczy w koszyku automatycznie się rerenderuje po naciśnięciu przycisku dodaj do koszyka który znajduje sie w komponencie Item który jest w Mainie. Czy da się tak zrobić żeby z tamtego miejsca wywołać rerendering komponentu header w którym jest koszyk?(chodzi o to żeby po dodaniu do koszyka numerek przy koszyku z ilością rzeczy się zwiększał bo podoba mi sie taka animcja  )

Header:

import React, { useState, useContext, useEffect } from 'react';

import { StoreContext } from '../../store/StoreProvider';
import logo from '../../images/sneakerssoriaLogo.png';

import './Header.scss';

const Header = () => {

    const [isHamburgerOpen, setIsHamburgerOpen] = useState(false);

    const handleButtonOnClick = () => setIsHamburgerOpen(prev => !prev);

    const { items } = useContext(StoreContext);

    let numberOfItemsInCart = items.filter(item => item.inCart[0] === true).length;

    return (
        <>
            <header>
                <div className="logo">
                    <img src={logo} className="logo__img" alt="logo" />
                </div>
                {isHamburgerOpen ? <div className="clickElement" onClick={handleButtonOnClick}></div> : null}
                <div className={`navigation ${isHamburgerOpen ? 'navigation--active' : ''}`}>
                    <ul className="navigation__list">
                        <li className="navigation__item"><a href="">Strona główna</a></li>
                        <li className="navigation__item"><a href="">Bluzy</a></li>
                        <li className="navigation__item"><a href="">Tshirty</a></li>
                        <li className="navigation__item"><a href="">Paski</a></li>
                        <li className="navigation__item"><a href="">Toeboxy</a></li>
                        <li className="navigation__item"><a href="">Opakowania</a></li>
                        <li className="navigation__item"><a href="">O nas</a></li>
                        <li className="navigation__item">
                            <i className="fab fa-facebook"></i>
                            <i className="fab fa-instagram"></i>
                        </li>
                    </ul>
                </div>
            </header>
            <div className="menu">
                <button className={`hamburger ${isHamburgerOpen ? 'hamburger--active' : ''}`} onClick={handleButtonOnClick}>
                    <span className="hamburger__box">
                        <span className="hamburger__inner"></span>
                    </span>
                </button>
                <i className="fas fa-search"></i>
                <i className="fas fa-shopping-basket">
                    <div className="yourCart">{numberOfItemsInCart}</div>
                </i>
            </div>
        </>
    );
};

export default Header;

Main

import React, { useContext } from 'react';

import Item from '../Item/Item';
import { StoreContext } from '../../store/StoreProvider';

import './Main.scss';

const Main = () => {

    const { items } = useContext(StoreContext);

    const itemsComponents = items.map(item => <Item key={item.id} {...item} />)

    return (
        <main>
            <ul>
                {itemsComponents}
            </ul>
        </main>
    );
};

export default Main;

Item:

import React, { useContext } from 'react';

import { StoreContext } from '../../store/StoreProvider';

import './Item.scss';

const Item = (props) => {

    const { id, img, sizes, name, price } = props;

    const { addToCart } = useContext(StoreContext);

    const sizesText = sizes.join(', ');

    const handleAddToCart = () => {
        addToCart(id);

        const cartInfo = document.querySelector(`[data-id='${id}']`)
        cartInfo.className = 'addToCartInfo addToCartInfo__visible';
        setTimeout(() => cartInfo.className = 'addToCartInfo', 2900);
    }

    return (
        <li className="item">
            <img className="productImage" src={img} alt="" />
            <p className="sizes">{sizesText}</p>
            <p className="title">{name}</p>
            <p className="price">{price}{price % 1 === 0 ? '.00' : null} zł</p>
            <button className="addToCart" onClick={handleAddToCart}>Dodaj do koszyka</button>
            <div className="addToCartInfo" data-id={id}><p>Dodano produkt do koszyka!</p></div>
        </li>
    );
};

export default Item;

store:

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

import toebox from '../images/toebox.jpeg';
import jacketBlue from '../images/jacketBlue.jpg';

export const StoreContext = createContext(null);

const DEFAULT_ITEMS = [
    {
        name: 'TOEBOXY Wkładki',
        price: 12,
        sizes: ['M', 'L'],
        id: 0,
        img: toebox,
        inCart: [false],
    },
    {
        name: 'The North Face 1996 Retro Nuptse Jacket',
        price: 900,
        sizes: ['S', 'M', 'L'],
        id: 1,
        img: jacketBlue,
        inCart: [false],
    }
]

const StoreProvider = ({ children }) => {
    const [items, setItems] = useState(DEFAULT_ITEMS);

    const addNewItem = (item) => setItems(prev => [...prev, item]);

    const addToCart = (id, size = 'S', amount = 1) => {
        const itemsCopy = items;
        itemsCopy.map(item => item.id === id ? item.inCart = [true, size, amount] : item);

        setItems(itemsCopy);
    }

    return (
        <StoreContext.Provider value={{
            items,
            addNewItem,
            addToCart,
        }}>
            {children}
        </StoreContext.Provider>
    )
}

export default StoreProvider;

 

komentarz 11 października 2021 przez pablop76 VIP (123,180 p.)
Wrzuć działający kod np. na github. Może wtedy ktoś się nad nim pochyli.

Zaloguj lub zarejestruj się, aby odpowiedzieć na to pytanie.

Podobne pytania

+1 głos
1 odpowiedź 354 wizyt
0 głosów
0 odpowiedzi 267 wizyt
0 głosów
1 odpowiedź 280 wizyt
pytanie zadane 29 stycznia 2021 w JavaScript przez sKodowany Obywatel (1,150 p.)

92,573 zapytań

141,423 odpowiedzi

319,645 komentarzy

61,959 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...