簡體   English   中英

當點擊 React 中的按鈕時,組件會渲染兩次

[英]When a button in React is clicked, the component renders twice

我對 React 很陌生,我正在制作一個電子商務網站以供練習。 我有一個購物車組件,可以從 API 動態呈現購物車項目,但我將問題 100% 縮小到前端。 在初始渲染時,它工作正常,數據庫購物車中的所有內容都會出現,但是在我按下購物車項目上的“從購物車中刪除”按鈕后,每個購物車項目都會翻倍。

CartCard.jsx(/api/delete 刪除后返回購物車的 json object。刪除在 api 中處理)

import React from "react";
import CartCardCSS from "./CartCard.module.css";

export default function CartCard(props) {
    const passCart = props.passCart;

    function deleteFromCart(e) {
        e.preventDefault();

        const item = {
            id: props.id,
            mainText: props.mainText,
            price: props.price,
            type: props.type
        }
        const user = {
            username: props.username
        }
        const compoundEntity = {
            theContent: item,
            theUser: user
        }


        const requestOptions = {
            method: "POST",
            headers: {"Content-Type" : "application/json"},
            body: JSON.stringify(compoundEntity)
        }


        fetch("/api/delete", requestOptions)
        .then(response => response.json())
        .then(response => {
            passCart(response)
            console.log(response)
        })


    }
    
    return (
        <div className={CartCardCSS.card}>
            <img src={props.image} className={CartCardCSS.itempicture} alt="item picture"/>
            <h3 className={CartCardCSS.subitem}>{props.mainText}</h3>
            <h4 className={CartCardCSS.subitem}>{props.price}</h4>
            <button onClick={deleteFromCart} className={`${CartCardCSS.subitem} ${CartCardCSS.button}`} type="button">Remove From Cart</button>
        </div>
    )
}

購物車.jsx:

import React, {useEffect, useState} from "react";
import CartCard from "./CartCard";

import CpuPicture from "./img/cpu.jpg";
import GpuPicture from "./img/gpu.jpg";


export default function Cart(props) {

    const cart = props.cart;
    const username = props.username;
    const passCart = props.passCart;
    const [arrCart, setArrCart] = useState(Object.values(cart))
    const [cartComp, setCartComp] = useState()

    useEffect(() => {

        console.log(cart)
        setArrCart(Object.values(cart))
    
        for(let i = 0; i < arrCart.length; i++) {
            setCartComp(arr => [arr, <CartCard key={i} id={i} passCart={passCart} username={username} mainText={arrCart[i].mainText} price={arrCart[i].price} type={arrCart[i].type} image={arrCart[i].type === "cpu" ? CpuPicture : GpuPicture}/>])
        }

    }, [cart])

    return (
        <div>
            <h2 >Cart:</h2>
            {cartComp}
        </div>
    )

}

配置文件.jsx:

import React from "react";
import Cart from "./Cart";
import Navbar from "./Navbar";

import {useNavigate} from "react-router-dom";


export default function Profile(props) {
    const username = props.username;
    const isLoggedIn = props.isLoggedIn;
    const cart = props.cart;
    const passCart = props.passCart;
    let navigate = useNavigate();
    const routeChange = () => {

        let path = "/login";
        navigate(path);
    }


    if (isLoggedIn) {
        return (
            <div>
                <Navbar />
                <h1>{username}</h1>
                <Cart passCart={passCart} username={username} cart={cart} />
    
            </div>
    
        )
    } else {
        
        routeChange();
    }

}

應用程序.jsx

import React, {useState} from "react";
import './App.css';
import Login from "./components/Login";
import Signup from "./components/Signup";
import Home from "./components/Home";
import Profile from "./components/Profile";
import Card from "./components/Card";
import GpuPicture from "./components/img/gpu.jpg";
import CpuPicture from "./components/img/cpu.jpg";

import {BrowserRouter, Routes, Route, Navigate} from "react-router-dom";

function App() {
  const [username, setUsername] = useState('');
  const [cart, setCart] = useState('');
  const [isLoggedIn, setIsLoggedIn] = useState(false)

  function passUsername(items) {
    setUsername(items);
  }
  function passCart(items) {
    setCart(items);

  }
  function passIsLoggedIn(items) {
    setIsLoggedIn(items);

  }



  return (
    <div className="App">
      <BrowserRouter>
        <Routes>
          <Route path="/" element={<Navigate to="/login"/>} />
          <Route path="/login" element={<Login passIsLoggedIn={passIsLoggedIn} passUsername={passUsername} passCart={passCart}/>}/>
          <Route path="/signup" element={<Signup />}/>
          <Route path="/home" element={<Home passCart={passCart} cart={cart} username={username} isLoggedIn={isLoggedIn} />} />
          <Route path="/profile" element={<Profile passCart={passCart} cart={cart} username={username} isLoggedIn={isLoggedIn}/>} />
        </Routes>
      </BrowserRouter>
    </div>
  );
}

export default App;

謝謝你的幫助

這個for循環可能是問題所在:

useEffect(() => {

    console.log(cart)
    setArrCart(Object.values(cart))
    
    for(let i = 0; i < arrCart.length; i++) {
        setCartComp(arr => [arr, <CartCard key={i} id={i} passCart={passCart} username={username} mainText={arrCart[i].mainText} price={arrCart[i].price} type={arrCart[i].type} image={arrCart[i].type === "cpu" ? CpuPicture : GpuPicture}/>])
    }

}, [cart])

請記住,react 中的setState是異步的。 這是什么意思:

console.log(arrCart) // previous state
setArrCart(Object.values(cart))
console.log(arrCart) // still previous state

嘗試將您的for循環更改為:

for(let i = 0; i < cart.length; i++) {
    setCartComp(arr => [arr, <CartCard key={i} id={i} passCart={passCart} username={username} mainText={cart[i].mainText} price={cart[i].price} type={cart[i].type} image={cart[i].type === "cpu" ? CpuPicture : GpuPicture}/>])
}

正如@deaponn提到的, useState是異步的。

setCartComp中的 for 循環被調用 n 次。 或者如何使用javascript的map function:

useEffect(() => {
    console.log(cart);
    // map transforms the array into an array of another type (in this case CartCard instances)
    setCartComp(Object.values(cart).map((item, index) =>
                    <CartCard key={index} id={index}
                              passCart={passCart}
                              username={username}
                              mainText={item.mainText}
                              price={item.price}
                              type={item.type}
                              image={item.type === "cpu" ? CpuPicture : GpuPicture} />));
}, [cart]);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM