ReactJS, как отображать компонент при изменении значения

у меня есть список желаний. Когда я добавляю элементы в свой список желаний, я добавляю элементы в свой 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 }}>&nbsp;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 }}>&nbsp;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 }}>&nbsp;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 }}>&nbsp;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;

что делает useEffect в этом коде? убери это.

Abbas Bagheri 13.04.2023 11:38

Что вы делаете, когда добавляете товар в список желаний? Причина предупреждения, вероятно, в том, что у вас бесконечный цикл. Вы слушаете изменение счета и обновляете его. Также if и else условие выглядит одинаково. В чем разница?

CodeThing 13.04.2023 11:47

просто рендеринг страницы, когда я добавляю или удаляю элемент из localStorage (когда изменяется [count], я ошибаюсь? (он показывает длину элементов в localStorage)

Ilkin Karimov 13.04.2023 11:49

@CodeThing Я получаю данные от API для отображения элементов на главной странице. и я добавил кнопку (добавить в список желаний), и когда я добавляю элемент в список желаний, я добавляю элемент в localStorage. мне нужно показать, сколько элементов я добавил в список желаний. Теперь я добавляю в список желаний (localStorage), но не могу показать, сколько элементов я добавил. когда я добавляю, это не отображается. когда я перезагружаю страницу, я вижу, сколько элементов я добавил

Ilkin Karimov 13.04.2023 11:54

В этом случае вам следует вместо этого добавить элемент в состояние подсчета. Таким образом, это будет правильно отображать обновленный счет. и useEffect просто прослушает его и соответственно обновит ваше локальное хранилище.

CodeThing 13.04.2023 11:56

@CodeThing не отображается и показывает количество, когда я изменяю (добавляю или удаляю) localStorage

Ilkin Karimov 13.04.2023 11:57

@CodeThing У меня есть useState на домашней странице (откуда я добавляю элементы в localStorage), он добавляет элементы в localStorage.

Ilkin Karimov 13.04.2023 11:58

@IlkinKarimov Добавлен ответ. пожалуйста, проверьте

CodeThing 13.04.2023 12:04

@CodeThing Сэр, я уже добавляю элементы в свое локальное хранилище с домашней страницы и (сколько элементов я добавил, должно быть показано в заголовке). мне нужно что-то сделать в компоненте заголовка. поэтому, когда я удаляю элемент со страницы списка желаний, он должен быть -1 каждый раз (когда я удаляю со страницы списка желаний)

Ilkin Karimov 13.04.2023 12:07

@CodeThing, так что мне просто нужно показать мне счет, когда я добавляю или удаляю элементы из localStorage. (из "понравилось") показывает только при перезагрузке страницы

Ilkin Karimov 13.04.2023 12:09

@IlkinKarimov Вам нужно обновить свое состояние, если вам нужно, чтобы ваше приложение отображало ваши изменения. только обновление localstorage не может повторно отобразить компонент. Для удаления также, как я уже упоминал в своем ответе ниже, вам просто нужно отфильтровать удаленные элементы из состояния.

CodeThing 13.04.2023 12:11

@CodeThing я добавил заголовок и проверьте productCard, пожалуйста

Ilkin Karimov 13.04.2023 12:27

Вы не можете прослушивать изменения в локальном хранилище. вам нужно либо поднять состояние (иметь состояние списка пожеланий в каком-то общем компоненте над этими компонентами), либо лучше использовать контекст

CodeThing 13.04.2023 12:33

МОЙ БОГ! Большое спасибо, братан. Я только что использовал Context, и теперь все в порядке! Большое спасибо!!!

Ilkin Karimov 13.04.2023 13:19
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
14
63
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как упоминалось в комментариях. Вы получаете предупреждение, потому что у вас бесконечный цикл, когда вы слушаете и обновляете одно и то же состояние.

Вот что вы можете попробовать. Когда вы нажимаете «Добавить в список желаний», просто обновите состояние счетчика. Добавьте новый элемент в существующий список пожеланий, хранящийся в состоянии подсчета. А затем 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>
  );
}

Другие вопросы по теме