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;