html ReactJS如何在改变值时渲染组件

yyyllmsg  于 2023-04-18  发布在  React
关注(0)|答案(1)|浏览(113)

我有愿望清单。当我添加项目到我的愿望清单,我添加项目到我的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.log(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.log("if", oldData)

        } else {
            oldData.push(likedItem)
            console.log("else", oldData)
        }
        localStorage.setItem("liked", JSON.stringify(oldData));
        console.log(oldData);
        handleFavouritesState();
    };
    const handleFavouritesState = () => {
        let oldData = JSON.parse(localStorage.getItem("liked")) ?? []
        let temp = oldData.map((likedItem) => likedItem.id);
        setFavourites([...temp])
        console.log("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;
b09cbbtk

b09cbbtk1#

正如在评论中提到的。你得到警告,因为你有无限循环,因为你正在监听和更新相同的状态。
您可以尝试以下操作。当您点击添加到愿望清单时,只需更新您的计数状态。将新项目添加到存储在计数状态中的现有愿望清单中。然后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>
  );
}

相关问题