[英]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.