Skip to content
Advertisement

Why do I get NaN value in react?

Whilst I am doing cart in react, I have no idea why I keep getting NaN value – only from a specific object data.

When I have the following data list:

#1 ItemsList.js

export const ItemsList = [
  {
    id: 1,
    name: "VA-11 Hall-A: Cyberpunk Bartender Action",
    price: 110000,
    image: cover1,
    link: "https://store.steampowered.com/app/447530/VA11_HallA_Cyberpunk_Bartender_Action/?l=koreana",
  },
...
  {
    id: 6,
    name: "Limbus Company",
    price: 110000,
    image: cover6,
    link: "https://limbuscompany.com/",
  },
];

And the following code, please look at the comment line.

#2 Goods.jsx

import React, { useContext } from "react";
import "./Goods.css";
import { DataContext } from "../../components/context/DataContext";

export const Goods = (props) => {
  const { id, name, price, image, link } = props.shopItemProps;
  const { cartItems, addItemToCart, removeItemFromCart } =
    useContext(DataContext);
  const cartItemStored = cartItems[id];

  return (
    <div className="goods">
      <div className="goods-id">{id}</div>
      <img src={image} alt="thumbnail_image" className="goods-image" />
      <div className="goods-name">{name}</div>
      <div className="goods-price">${price}</div>
      <button>
        <a href={link} className="goods-link">
          Official Store Page
        </a>
      </button>
      <div className="cart-button">
        <button onClick={() => removeItemFromCart(id)}>-</button>
// ★Maybe here? but why do I get NaN only for id:6? Others work well.
        {cartItemStored > -1 && <> ({cartItemStored}) </>}
        <button onClick={() => addItemToCart(id)}>+</button>
      </div>
    </div>
  );
};

What should I do to solve NaN? There seems to be no way to make that value as int in this case. Or do you see any problem from the above code block?

Edited

Sorry for confusing you. Here are the additional code related.

#3. DataContext.js (where cartItems state exists)

import React, { createContext, useState } from "react";
import { ItemsList } from "../ItemsList";

export const DataContext = createContext(null);

const getDefaultCart = () => {
  let cart = {};
  for (let i = 1; i < ItemsList.length; i++) {
    cart[i] = 0;
  }
  return cart;
};

export const DataContextProvider = (props) => {
  const [cartItems, setCartItems] = useState(getDefaultCart);

  const checkoutTotalSum = () => {
    let totalAmount = 0;
    for (const item in cartItems) {
      if (cartItems[item] > 0) {
        let itemInfo = ItemsList.find((product) => product.id === Number(item));
        totalAmount += cartItems[item] * itemInfo.price;
      }
    }
    return totalAmount;
  };

  const addItemToCart = (itemId) => {
    setCartItems((prev) => ({ ...prev, [itemId]: prev[itemId] + 1 }));
  };

  const removeItemFromCart = (itemId) => {
    setCartItems((prev) => ({ ...prev, [itemId]: prev[itemId] - 1 }));
  };

  const updateCartItemCount = (newAmount, itemId) => {
    setCartItems((prev) => ({ ...prev, [itemId]: newAmount }));
  };

  const contextValue = {
    cartItems,
    addItemToCart,
    removeItemFromCart,
    updateCartItemCount,
    checkoutTotalSum,
  };

  // console.log(cartItems);

  return (
    <DataContext.Provider value={contextValue}>
      {props.children}
    </DataContext.Provider>
  );
};

Advertisement

Answer

The issue is in the function you are using to set the initial value of cartItems, more specifically, in the for loop. This line is the culprit: i < ItemsList.length, when in your case, it should be i <= ItemsList.length. Why? because you are not including the last element of ItemsList on the cart object (you are initializing the i counter with 1 and ItemsList‘s length is 6).

So, when you call addItemToCart:

const addItemToCart = (itemId) => {
  setCartItems((prev) => ({ ...prev, [itemId]: prev[itemId] + 1 }));
};

And try to update the value corresponding to the last element of ItemsList which is 6 in cartItems, you’re getting: '6': undefined + 1 because again, you did skip the last element in the for loop. This results in NaN.

You also have the option of initializing i with 0 and preserve this line: i < ItemsList.length, or:

for (let i = 1; i < ItemsList.length + 1; i++) {
  ...
} 
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement