у меня есть список желаний. Когда я добавляю элементы в свой список желаний, я добавляю элементы в свой localStorage. И мне нужно показать, сколько предметов я добавил в свой список желаний. я не знаю, как отображать заголовок (автоматически) при изменении значения в (localStorage).
Когда я добавляю элементы в список желаний, он отображается в теге span, все хорошо, но в консоли я получаю: Предупреждение: превышена максимальная глубина обновления.
Может кто-нибудь помочь, пожалуйста? Все находится на компоненте заголовка (странице) Заглавная страница:
import React, { useContext, useState, useEffect } from 'react';
import { Container, Navbar, Nav } from 'react-bootstrap';
import { ThemeContext } from '../GlobalComponents/ThemeProvider';
import { BiSun, BiMoon, BiCart } from 'react-icons/bi';
import { VscAccount } from 'react-icons/vsc';
import { Link } from "@reach/router";
import { useCart } from "react-use-cart";
import { useAuth0 } from "@auth0/auth0-react";
const Header = () => {
const { theme, setThemeMode } = useContext(ThemeContext);
const [darkMode, setDarkMode] = useState(theme);
const { loginWithRedirect, logout, isAuthenticated, user, isLoading } = useAuth0();
const [count, setCount] = useState((JSON.parse(localStorage.getItem("liked"))));
const cou = () => {
let oldData = JSON.parse(localStorage.getItem('liked') || "[]")
if (oldData.length === count.length) {
setCount((JSON.parse(localStorage.getItem("liked"))))
} else {
setCount((JSON.parse(localStorage.getItem("liked"))))
}
};
useEffect(() => {
let oldData = JSON.parse(localStorage.getItem('liked') || "[]")
if (oldData.length === count.length) {
setCount((JSON.parse(localStorage.getItem("liked"))))
} else {
setCount((JSON.parse(localStorage.getItem("liked"))))
}
}, [count]);
useEffect(() => {
setThemeMode(darkMode);
console.info(darkMode)
}, [darkMode]);
const {
isEmpty,
totalItems,
} = useCart();
if (isLoading) {
return (
<Navbar collapseOnSelect expand = "md"
variant = {darkMode ? 'dark' : 'light'}
className = {darkMode ? 'bg-light-black border-bottom' : 'bg-light border-bottom'}
style = {{ width: '100%', position: 'fixed', zIndex: 100 }}
>
<Container>
<Link to = "/">
<Navbar.Brand className = {darkMode ? 'text-dark-primary' : 'text-light-primary'}>
<img src='https://i.ibb.co/7kZrn4H/33342.png' width = {200} />
</Navbar.Brand>
</Link>
<Navbar.Toggle aria-controls = "basic-navbar-nav" />
<Navbar.Collapse id = "basic-navbar-nav">
<Nav className = "ms-auto">
<div className='load'><div class = "lds-ellipsis"><div></div><div></div><div></div><div></div></div></div>
<Nav.Link
className = {darkMode ? 'text-dark-primary' : 'text-light-primary'}
onClick = {() => setDarkMode(!darkMode)}
>
{darkMode ? <BiSun size = "1.7rem" /> : <BiMoon size = "1.7rem" />}
</Nav.Link>
<Link
to = "/cart"
className = {`${darkMode ? 'text-dark-primary' : 'text-light-primary'} d-flex align-items-center`}
>
<BiCart size = "2rem" />
{!isEmpty && <span style = {{ position: 'relative', left: '-21px', top: '-18px' }}>{totalItems}</span>}
<span style = {{ marginLeft: !isEmpty ? '-13px' : 0 }}> Cart</span>
</Link>
<Link
to = "/wishlist"
className = {`${darkMode ? 'text-dark-primary' : 'text-light-primary'} d-flex align-items-center`}
>
<BiCart size = "2rem" />
{!isEmpty && <span style = {{ position: 'relative', left: '-21px', top: '-18px' }}></span>}
<span style = {{ marginLeft: !isEmpty ? '-13px' : 0 }}> Wishlist</span>
</Link>
{
isAuthenticated ? (
<>
<button onClick = {() => logout({ logoutParams: { returnTo: window.location.origin } })} className = {`login-btn ${darkMode ? 'text-dark-primary' : 'text-light-primary'}`}>
Log Out
</button>
</>
) : (
<>
<button onClick = {() => loginWithRedirect()} className = {`login-btn ${darkMode ? 'text-dark-primary' : 'text-light-primary'}`}>
Log in
</button>
</>
)
}
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
);
};
return (
<Navbar collapseOnSelect expand = "md"
variant = {darkMode ? 'dark' : 'light'}
className = {darkMode ? 'bg-light-black border-bottom' : 'bg-light border-bottom'}
style = {{ width: '100%', position: 'fixed', zIndex: 100 }}
>
{/* <button onClick = {()=>cou()}>Ref</button> */}
<Container>
<Link to = "/">
<Navbar.Brand className = {darkMode ? 'text-dark-primary' : 'text-light-primary'}>
<img src='https://i.ibb.co/7kZrn4H/33342.png' width = {200} />
</Navbar.Brand>
</Link>
<Navbar.Toggle aria-controls = "basic-navbar-nav" />
<Navbar.Collapse id = "basic-navbar-nav">
<Nav className = "ms-auto">
{
isAuthenticated && (
<>
<p className = {`d-flex align-items-center user-name ${darkMode ? 'text-dark-primary' : 'text-light-primary'}`}>{user.email}</p>
</>
)
}
<Nav.Link
className = {darkMode ? 'text-dark-primary' : 'text-light-primary'}
onClick = {() => setDarkMode(!darkMode)}
>
{darkMode ? <BiSun size = "1.7rem" /> : <BiMoon size = "1.7rem" />}
</Nav.Link>
<Link
to = "/cart"
className = {`${darkMode ? 'text-dark-primary' : 'text-light-primary'} d-flex align-items-center`}
>
<BiCart size = "2rem" />
{!isEmpty && <span style = {{ position: 'relative', left: '-21px', top: '-18px' }}>{totalItems}</span>}
<span style = {{ marginLeft: !isEmpty ? '-13px' : 0 }}> Cart</span>
</Link>
<Link
to = "/wishlist"
className = {`${darkMode ? 'text-dark-primary' : 'text-light-primary'} d-flex align-items-center`}
>
<BiCart size = "2rem" />
{!isEmpty && <span style = {{ position: 'relative', left: '-21px', top: '-18px' }}>{count.length}</span>}
<span style = {{ marginLeft: !isEmpty ? '-13px' : 0 }}> Wishlist</span>
</Link>
{
isAuthenticated ? (
<>
<button onClick = {() => logout({ logoutParams: { returnTo: window.location.origin } })} className = {`login-btn ${darkMode ? 'text-dark-primary' : 'text-light-primary'}`}>
Log Out
</button>
</>
) : (
<>
<button onClick = {() => loginWithRedirect()} className = {`login-btn ${darkMode ? 'text-dark-primary' : 'text-light-primary'}`}>
Log in
</button>
</>
)
}
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
);
};
export default Header;
Страница карточки товара:
import React, { useState } from 'react';
import { Button, Card } from 'react-bootstrap';
import { useThemeHook } from '../GlobalComponents/ThemeProvider';
import { useCart } from 'react-use-cart';
import { BsCartPlus } from 'react-icons/bs';
import { Link } from "@reach/router";
import { useInView } from 'react-intersection-observer';
const ProductCard = (props) => {
// const [state,setState]=useState({
// favourites:[]
// });
const [favourites, setFavourites] = useState([]);
let { image, price, title, id } = props.data;
const [theme] = useThemeHook();
const { addItem } = useCart();
const { ref: headerAni, inView: headerAniVisible } = useInView();
const addToCart = () => {
addItem(props.data);
}
const handleFavourites = (likedItem) => {
let oldData = JSON.parse(localStorage.getItem('liked')) ?? []
if (favourites.includes(likedItem.id)) {
oldData = oldData.filter((m) => m.id !== likedItem.id)
console.info("if", oldData)
} else {
oldData.push(likedItem)
console.info("else", oldData)
}
localStorage.setItem("liked", JSON.stringify(oldData));
console.info(oldData);
handleFavouritesState();
};
const handleFavouritesState = () => {
let oldData = JSON.parse(localStorage.getItem("liked")) ?? []
let temp = oldData.map((likedItem) => likedItem.id);
setFavourites([...temp])
console.info("son", oldData)
};
return (
<>
<Card
style = {{ width: '18rem', height: 'auto' }}
className = {`${theme ? 'bg-light-black text-light' : 'bg-lihgt text-black'} text-center p-0 overflow-hidden shadow mx-auto mb-4`}
ref = {headerAni}
>
<Link to = {`/product-details/${id}`}>
<div style = {{
background: 'white', height: '15rem', overflow: 'hidden', display: 'flex',
justifyContent: 'center', alignItems: 'center', marginBottom: 'inherit'
}}>
<div style = {{ width: '9rem' }}>
<Card.Img variant = "top" src = {image} className = "img-fluid" data-aos-easing = "ease-out-cubic"
data-aos-duration = "3000" data-aos = {`${headerAniVisible ? "" : "zoom-out"}`} />
</div>
</div>
</Link>
<Card.Body>
<Card.Title style = {{ textOverflow: 'ellipsis', overflow: 'hidden', whiteSpace: 'nowrap' }}>
{title}
</Card.Title>
<Card.Title>
$ <del><span className = "">{price * 2}</span></del>
</Card.Title>
<Card.Title>
$ <span className = "h3">{price}</span>
</Card.Title>
<Button
onClick = {() => addToCart()}
className = {`${theme ? 'bg-dark-primary text-black' : 'bg-light-primary'} d-flex align-item-center m-auto border-0`}
>
<BsCartPlus size = "1.8rem" />
Add to cart
</Button>
<Button
onClick = {() => handleFavourites(props.data)}
className = {`${theme ? 'bg-dark-primary text-black' : 'bg-light-primary'} d-flex align-item-center m-auto border-0`}
>
<BsCartPlus size = "1.8rem" />
Add to Favourites
</Button>
</Card.Body>
</Card>
</>
);
};
export default ProductCard;
Что вы делаете, когда добавляете товар в список желаний? Причина предупреждения, вероятно, в том, что у вас бесконечный цикл. Вы слушаете изменение счета и обновляете его. Также if и else условие выглядит одинаково. В чем разница?
просто рендеринг страницы, когда я добавляю или удаляю элемент из localStorage (когда изменяется [count], я ошибаюсь? (он показывает длину элементов в localStorage)
@CodeThing Я получаю данные от API для отображения элементов на главной странице. и я добавил кнопку (добавить в список желаний), и когда я добавляю элемент в список желаний, я добавляю элемент в localStorage. мне нужно показать, сколько элементов я добавил в список желаний. Теперь я добавляю в список желаний (localStorage), но не могу показать, сколько элементов я добавил. когда я добавляю, это не отображается. когда я перезагружаю страницу, я вижу, сколько элементов я добавил
В этом случае вам следует вместо этого добавить элемент в состояние подсчета. Таким образом, это будет правильно отображать обновленный счет. и useEffect просто прослушает его и соответственно обновит ваше локальное хранилище.
@CodeThing не отображается и показывает количество, когда я изменяю (добавляю или удаляю) localStorage
@CodeThing У меня есть useState на домашней странице (откуда я добавляю элементы в localStorage), он добавляет элементы в localStorage.
@IlkinKarimov Добавлен ответ. пожалуйста, проверьте
@CodeThing Сэр, я уже добавляю элементы в свое локальное хранилище с домашней страницы и (сколько элементов я добавил, должно быть показано в заголовке). мне нужно что-то сделать в компоненте заголовка. поэтому, когда я удаляю элемент со страницы списка желаний, он должен быть -1 каждый раз (когда я удаляю со страницы списка желаний)
@CodeThing, так что мне просто нужно показать мне счет, когда я добавляю или удаляю элементы из localStorage. (из "понравилось") показывает только при перезагрузке страницы
@IlkinKarimov Вам нужно обновить свое состояние, если вам нужно, чтобы ваше приложение отображало ваши изменения. только обновление localstorage не может повторно отобразить компонент. Для удаления также, как я уже упоминал в своем ответе ниже, вам просто нужно отфильтровать удаленные элементы из состояния.
@CodeThing я добавил заголовок и проверьте productCard, пожалуйста
Вы не можете прослушивать изменения в локальном хранилище. вам нужно либо поднять состояние (иметь состояние списка пожеланий в каком-то общем компоненте над этими компонентами), либо лучше использовать контекст
МОЙ БОГ! Большое спасибо, братан. Я только что использовал Context, и теперь все в порядке! Большое спасибо!!!
Как упоминалось в комментариях. Вы получаете предупреждение, потому что у вас бесконечный цикл, когда вы слушаете и обновляете одно и то же состояние.
Вот что вы можете попробовать. Когда вы нажимаете «Добавить в список желаний», просто обновите состояние счетчика. Добавьте новый элемент в существующий список пожеланий, хранящийся в состоянии подсчета. А затем useEffect позаботится о добавлении/синхронизации списка желаний в локальное хранилище.
export default function App() {
// Initial state will pull wishlist items from localstorage and set it in state
const [count, setCount] = useState(JSON.parse(localStorage.getItem("liked")) || []);
// This is your add to wishlist function. You can create similar function to remove item from wishlist. In that case you just need to filter the count state.
const addToWishlist = (item) => {
setCount(prev => [...prev, item]);
};
// This will update your localstorage whenever state changes.
useEffect(() => {
localStorage.setItem("liked", JSON.stringify(count));
}, [count]);
return (
<div>
<h1>Wishlist</h1>
<h2>{count.length}</h2>
<button onClick = {() => addToWishlist({id: 1, name: 'test'})}>Add to Wishlist</button>
</div>
);
}
что делает
useEffect
в этом коде? убери это.