需要有关如何解决唯一关键道具错误的指导

问题描述 投票:0回答:1

我正在一家电子商务商店工作,我已经设置了一个具有唯一 id 的产品页面,并循环遍历这些项目来显示它们,但在结账页面上,当我尝试删除某个项目时,我突然得到了一个 nan 值。这是我从中提取项目作为测试的页面。

这是填充购物车中的商品的产品页面,但如果购物车中有 2 个或更多商品,当我从购物车中删除商品时,我会收到唯一键错误。 下面是购物车页面,显示购物车中的商品

我已经为密钥提供了产品的唯一标识符,但现在我收到一个新错误“警告:列表中的每个子项都应该有一个唯一的“key”属性。当我删除项目时,这会导致购物车中出现 nan 。 ” 我有点卡在这里了。

import * as React from 'react';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import Typography from '@mui/material/Typography';
import Modal from '@mui/material/Modal';
import products from './product'
import { useContext } from 'react';
import { useState, useEffect} from 'react';


import cart from '../context/cart'
import { CartContext } from '../context/cart';
const style = {
  position: 'absolute',
  top: '50%',
  left: '50%',
  transform: 'translate(-50%, -50%)',
  width: "100%",
  bgcolor: 'background.paper',
  border: '2px solid #000',
  boxShadow: 24,
  p: 4,
};
export default function BasicModal() {
  const [open, setOpen] = React.useState(false);
  const handleOpen = () => setOpen(true);
  const handleClose = () => setOpen(false);


  const { cartItems, addToCart, removeFromCart, clearCart, getCartTotal } = useContext(CartContext)
  useEffect(() => {
    // storing input name
    localStorage.getItem("cartItems", JSON.stringify(cartItems));
  }, [cartItems])


// payment is processed here

  return (
    <div>
      <Button onClick={handleOpen}   >

        ({cartItems.length})
        Check Out</Button>
      <Modal
      disableScrollLock={true}
      fullScreen={true}
        open={open}
        onClose={handleClose}
        aria-labelledby="modal-modal-title"
        aria-describedby="modal-modal-description"
      >
        <Box sx={style}>
          <>
            <div className="flex-col flex items-center bg-white gap-8 p-10 text-black text-sm">
              <h1 className="text-2xl font-bold">Cart</h1>
              <div className="flex flex-col gap-4">
  
  
                {cartItems.map((item) => (
                  <div className="flex justify-between items-center" key={products.id}>
                    <div className="flex gap-4">
                      <img src={item.imageId} key="2014" alt={item.title} className="rounded-md h-24" />
                      <div className="flex flex-col">
                        <h1 className="text-lg font-bold" key="2015">{item.title}</h1>
                        <p className="text-gray-600" key="2013">{item.price}</p>
                        <p className="text-gray-600" key="202">{item.description}</p>

                      </div>
                    </div>
                    <div className="flex gap-4">
                      <button
                        className="px-4 py-2 bg-gray-800 text-white text-xs font-bold uppercase rounded hover:bg-gray-700 focus:outline-none focus:bg-gray-700"
                        onClick={() => {
                          addToCart(item)
                        }}
                      >
                        +
                      </button>
                      <p>{item.quantity}</p>
                      <button
                        className="px-4 py-2 bg-gray-800 text-white text-xs font-bold uppercase rounded hover:bg-gray-700 focus:outline-none focus:bg-gray-700"
                        onClick={() => {
                          removeFromCart(item)
                        }}
                      >
                        -
                      </button>

                    </div>
                  </div>
                ))}
              </div>
              {
                cartItems.length > 0 ? (
                  <div className="flex flex-col justify-between items-center">
                    <h1 className="text-lg font-bold">Total: ${getCartTotal()}</h1>
                    <button
                      className="px-4 py-2 bg-gray-800 text-white text-xs font-bold uppercase rounded hover:bg-gray-700 focus:outline-none focus:bg-gray-700"
                      onClick={() => {
                        clearCart()
                      }}
                    >
                      Clear cart
                    </button>
{/* check out here */}
        
                    {/* <Button variant="primary" onClick={} >Check out
                      </Button>  */}
                  </div>

                ) : (
                  <>
                    <h1 className="text-lg font-bold">Your cart is empty</h1>

                  </>
                )
              }
            </div>
            <div class="col d-flex justify-content-center">
 </div>
          </>
        </Box>
      </Modal>
    </div>
  );
} 

这就是我的背景

import { createContext, useState, useEffect } from 'react'
import  React from 'react'
import products from '../components/product';
export const CartContext = createContext()

export const CartProvider = ({ children }) => {
  const [cartItems, setCartItems] = useState(localStorage.getItem('cartItems') ? JSON.parse(localStorage.getItem('cartItems')) : [0])

  const addToCart = (item) => {
    const isItemInCart = cartItems.find((cartItem) => cartItem.id === item.id);

    if (isItemInCart) {
      setCartItems(
        cartItems.map((cartItem) =>
          cartItem.id === item.id
            ? { ...cartItem, quantity: cartItem.quantity + 1 }
            : cartItem
        )
      );
    } else {
      setCartItems([...cartItems, { ...item, quantity: 1 }]);
    }
  };

  const removeFromCart = (item) => {
    const isItemInCart = cartItems.find((cartItem) => cartItem.id === item.id);

    if (isItemInCart && isItemInCart.quantity === 1) {

      setCartItems(cartItems.filter((cartItem) => cartItem.id !== item.id));
    } else {
      setCartItems(
        cartItems.map((cartItem) =>
          cartItem.id === item.id
            ? { ...cartItem, quantity: cartItem.quantity - 1 }
            : 0,
          )
      );
    }
  };

  const clearCart = () => {
    setCartItems([]);
  };

  const getCartTotal = () => { 
    // cart item total is being added here
    return cartItems.reduce((total, cartItem) => total + cartItem.price * cartItem.quantity, 0);
  };

  useEffect(() => {
    localStorage.setItem("cartItems", JSON.stringify(cartItems));
  }, [cartItems]);

  useEffect(() => {
    const cartItems = localStorage.getItem("cartItems");
    if (cartItems) {
      setCartItems(JSON.parse(cartItems));
    }
  }, []);

  const initialValue = 0;
  const total = cartItems.reduce((accumulator,current) => accumulator + current.price * current.quantity, initialValue)


  return (
    <CartContext.Provider
      value={{
        cartItems,
        addToCart,
        removeFromCart,
        clearCart,
        getCartTotal,
      }}
    >
      {children}
    </CartContext.Provider>
  );
};

我该如何解决这个问题。

如果购物车中有超过 2 件商品,每当我从购物车中删除商品时,我都会收到一个 nan 错误。不确定如何解决这个问题。

          {cartItems.map((item) => (
                  <div className="flex justify-between items-center" key={products.id}>
                    <div className="flex gap-4">
                      <img src={item.imageId} key="2014" alt={item.title} className="rounded-md h-24" />
                      <div className="flex flex-col">
                        <h1 className="text-lg font-bold" key="2015">{item.title}</h1>
                        <p className="text-gray-600" key="2013">{item.price}</p>
                        <p className="text-gray-600" key="202">{item.description}</p>

                      </div>

目前这是我当前的错误index.js:1210警告:列表中的每个子项都应该有一个唯一的“key”属性。

检查

BasicModal
的渲染方法。

reactjs arrays e-commerce
1个回答
0
投票

通过为地图中的每个项目添加唯一的键,我最终解决了这个问题。

这是购物车的上下文。

import { createContext, useState, useEffect } from 'react'
import React from 'react';
export const CartContext = createContext()

export const CartProvider = ({ children }) => {
  const [cartItems, setCartItems] = useState(localStorage.getItem('cartItems') ? JSON.parse(localStorage.getItem('cartItems')) : [])

  const addToCart = (item) => {
    const isItemInCart = cartItems.find((cartItem) => cartItem.id === item.id);

    if (isItemInCart) {
      setCartItems(
        cartItems.map((cartItem) =>
          cartItem.id === item.id
            ? { ...cartItem, quantity: cartItem.quantity + 1 }
            : cartItem
        )
      );
    } else {
      setCartItems([...cartItems, { ...item, quantity: 1 }]);
    }
  };

  const removeFromCart = (item) => {
    const isItemInCart = cartItems.find((cartItem) => cartItem.id === item.id);

    if (isItemInCart.quantity === 1) {
      setCartItems(cartItems.filter((cartItem) => cartItem.id !== item.id));
    } else {
      setCartItems(
        cartItems.map((cartItem) =>
          cartItem.id === item.id
            ? { ...cartItem, quantity: cartItem.quantity - 1 }
            : cartItem
        )
      );
    }
  };

  const clearCart = () => {
    setCartItems([]);
  };

  const getCartTotal = () => {
    return cartItems.reduce((total, item) => total + item.price * item.quantity, 0);
  };

  useEffect(() => {
    localStorage.setItem("cartItems", JSON.stringify(cartItems));
  }, [cartItems]);

  useEffect(() => {
    const cartItems = localStorage.getItem("cartItems");
    if (cartItems) {
      setCartItems(JSON.parse(cartItems));
    }
  }, []);

  return (
    <CartContext.Provider
      value={{
        cartItems,
        addToCart,
        removeFromCart,
        clearCart,
        getCartTotal,
      }}
    >
      {children}
    </CartContext.Provider>
  );
};

这是结帐购物车的更新代码

import * as React from 'react';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import axios from 'axios';
import Button from '@mui/material/Button';
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogContentText from '@mui/material/DialogContentText';
import DialogTitle from '@mui/material/DialogTitle';
import { CartContext } from '../context/cart';
import Axios from 'axios';
import { useContext } from 'react';
import { useState, useEffect} from 'react';
export default function AlertDialog() {
  const [open, setOpen] = React.useState(false);

  const { cartItems, addToCart, removeFromCart, clearCart, getCartTotal } = useContext(CartContext)
  useEffect(() => {
    // storing input name
    localStorage.getItem("cartItems", JSON.stringify(cartItems));
  }, [cartItems])


  const handleCheckout = () => {
    
    
    ;
  };

  const handleClickOpen = () => {
    setOpen(true);
  };

  const handleClose = () => {
    setOpen(false);
  };
  const style = {
    position: 'absolute',
    top: '50%',
    left: '50%',
    transform: 'translate(-50%, -50%)',
    width: "100%",
    bgcolor: 'background.paper',
    border: '2px solid #000',
    boxShadow: 24,
    p: 4,
  };
  return (
    <React.Fragment>
      <Button variant="outlined" onClick={handleClickOpen}>
        Confirm check out here
      </Button>
      <Dialog
        open={open}
        disableScrollLock={false}
        fullScreen={true}
        onClose={handleClose}
        aria-labelledby="alert-dialog-title"
        aria-describedby="alert-dialog-description"
      >
        <DialogTitle id="alert-dialog-title">
          {"Cofirm check out here?"}
        </DialogTitle>
        <DialogContent>
         
        <Box sx={style}>
          <>
            <div className="flex-col flex items-center bg-white gap-8 p-10 text-black text-sm">
              <h1 className="text-2xl font-bold">Cart</h1>
              <div className="flex flex-col gap-4">
              
                {cartItems.map((item) => (
                  <div className="flex justify-between items-center" key={item.id} id={item.id}>
                    <div  className="flex gap-4">
                      <img  src={item.imageId} key={item.imageId  } alt={item.title} className="rounded-md h-24" />
                      <div className="flex flex-col">
                        <h1 className="text-lg font-bold" key={item.title  } >{item.title} </h1>
                        <p  className="text-gray-600" key={item.price  } > {item.price}</p>
                        <p  className="text-gray-600"key={item.description  }>{item.description} </p>

                      </div>
                    </div>
                    <div className="flex gap-4">
                      <button
                        className="px-4 py-2 bg-gray-800 text-white text-xs font-bold uppercase rounded hover:bg-gray-700 focus:outline-none focus:bg-gray-700"
                        onClick={() => {
                          addToCart(item)
                        }}
                      >
                        +
                      </button>
                      <p >{item.quantity}</p>
                      <button
                        className="px-4 py-2 bg-gray-800 text-white text-xs font-bold uppercase rounded hover:bg-gray-700 focus:outline-none focus:bg-gray-700"
                        onClick={() => {
                          removeFromCart(item)
                        }}
                      >
                        -
                      </button>

                    </div>
                  </div>
                ))}
              
              </div>
          
              {
                cartItems.length > 0 ? (
                  <div className="flex flex-col justify-between items-center">
                    <h1 className="text-lg font-bold">Total: ${getCartTotal()}</h1>
                    <button
                      className="px-4 py-2 bg-gray-800 text-white text-xs font-bold uppercase rounded hover:bg-gray-700 focus:outline-none focus:bg-gray-700"
                      onClick={() => {
                        clearCart()
                      }}
                    >
                      Clear cart
                    </button>
{/* check out here */}



{/* check out here */}
        

                    {/* <Button variant="primary" onClick={} >Check out
                      </Button>  */}
                  </div>

                ) : (
                  <>
                    <h1 className="text-lg font-bold">Your cart is empty</h1>
                  </>
                )
              }
            </div>
            <div class="col d-flex justify-content-center">
 </div> 
          </>
        </Box>


        </DialogContent>
        <DialogActions>
          <Button onClick={handleClose}>Close Check Out</Button>
          <Button onClick={handleCheckout} autoFocus>
            Check out and pay
          </Button>
        </DialogActions>
      </Dialog>
    </React.Fragment>
  );
}
© www.soinside.com 2019 - 2024. All rights reserved.