skip to Main Content

I am trying to make a table that implements total price but it equals Nan

how the total is calculated:

  import React from 'react';
    
    const Total = (props) => {
        const {items} = props;
        let total = 0
        for (let i = 0; i < items.length; i++) {
            total += parseFloat(items[i].price)
        }
        return (
            <div>
                <p className="text">Total Price: {total}</p>
            </div>
        )
    }
    
    export default Total;

we add items by two buttons, the add button and the + button:

enter image description here

enter image description here

the console shows no errors

here is the app.js:

import './App.css';
import React, {Component} from 'react';
import Items from './components/item/items'
import AddItem from './components/addItem/addItem'
import Total from './components/total/total'

class App extends Component {
  state = {
    items: [
      {id:1, product:'Pen', price:2},
      {id:2, product:'Book', price:10}
    ]
  }

  deleteItem = (id) => {
    let items = this.state.items
    let i = items.findIndex(item => item.id === id)
    items.splice(i, 1)
    this.setState({items: items})
  }

  
  addItem = (item) => {
    this.setState({items: [...this.state.items, {id: this.state.items.length > 0 ? (this.state.items[this.state.items.length - 1].id + 1): 1}]
  })}
  
addItem2 = (item) => {
  this.state.items.length > 0 ? (
    item.id = this.state.items[this.state.items.length - 1].id + 1 
  ) : item.id = 1
  console.log(item.id)
  let items = this.state.items
  items.push(item)
  this.setState({items: items})
}

  render() {
    return (
      <div className="container">
        <h1>Product List React App</h1>
        <div className="table">
          <Items items={this.state.items} del={this.deleteItem} add={this.addItem}/>
          <AddItem add={this.addItem2}/>
          <Total items={this.state.items}/>
          
        </div>
      </div>
    )
  }
}

export default App;

here is the items.js:

import React from 'react';

const Items = (props) => {
    const {items, del,add} = props;
    let length = items.length
    const ListItem = length ? (
        items.map(item => {
            return(
                <div key={item.id} className="item">
                    <p  onClick={()=>add(item.id)}>+</p>
                    
                    <p>{item.product}</p>
                    <p>{item.price}</p>
                    <p className="delete" onClick={() => del(item.id)}>&times;</p>
                    
                </div>
            )
        })
    ) : (
        <div className="text">There are no items, Try to add some.</div>
    )
    return (
        <div>
            <div className="header item">
                <p>quantity</p>
                
                <p>Product</p>
                <p>Price</p>
                
                <p>Edit</p>
                
            </div>
           
            {ListItem}
        </div>
    )
}

export default Items

the console shows the product and the price and it shows no errors until now

2

Answers


  1. TL,DR: One of the items is either a string, undefined or anything that cannot be converted into a number.

    Source: developer.mozilla.org – NaN – Description

    Long Story Short:

    If you’re getting a NaN (Not a Number) result, it indicates that at least one of the values in the items array’s price property cannot be successfully converted to a number using parseFloat. To prevent this issue, you should ensure that each price value is a valid number before attempting to add it to the total.

    Here’s an updated version of your code that includes a check to handle potential non-numeric values:

    import React from 'react';
    
    const Total = (props) => {
        const { items } = props;
        let total = 0;
    
        for (let i = 0; i < items.length; i++) {
            // Ensure that the price is a valid number before adding it to the total
            const price = parseFloat(items[i].price);
            
            if (!isNaN(price)) {
                total += price;
            }
        }
    
        return (
            <div>
                <p className="text">Total Price: {total}</p>
            </div>
        );
    }
    
    export default Total;
    
    

    By using parseFloat and checking if the result is a valid number using isNaN, you can prevent NaN values from being added to the total. This should help resolve the issue you’re encountering.

    Another possible case scenario:

      // this goes fine
      let someValue = "100";
      let value = parseFloat(someValue);
    
      // but depending on your region, this, for instance, might generate a NaN
      somevalue = "1,000.00";
      let value = parseFloat(someValue);
    

    In Your Specific Case:

    The issue causing NaN in the total price is in the addItem method where you’re trying to calculate the next id. Let’s fix that part:

    addItem = (item) => {
        const newItem = {
            id: this.state.items.length > 0 ? this.state.items[this.state.items.length - 1].id + 1 : 1,
            product: item.product,
            price: parseFloat(item.price) || 0,  // Ensure price is a valid number or default to 0
        };
    
        this.setState({ items: [...this.state.items, newItem] });
    }
    

    Explanation:

    • Added parseFloat(item.price) || 0 to ensure that the price is converted to a valid number. If it fails, it defaults to 0.
      This modification should prevent NaN from appearing in the total price.
    Login or Signup to reply.
  2. Reason: your items list has an empty price. it will be either an empty string or undefined.

    Solution:
    correct the code as below:

    for (let i = 0; i < items.length; i++) {
            total += parseFloat(items[i].price || 0)
    }
    

    So, in case the price of an item is a falsy value, it will fall back to zero and avoid the NaN.

    Changed line: parseFloat(items[i].price || 0)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search