-1

I have a React.js shopping cart with 4 items, each item has a different value to 2 decimal places like so:

Item 1 = price:0.50
Item 2 = price:0.30
Item 3 = price:0.20
Item 4 = price:0.15

When I add Item 1 (value of 0.50) to the cart it adds correctly and I can add several of Item 1 to the cart and it will always remain to 2 decimal places. However, if I add any of the other 3 items to the cart, on the third addition to the cart it returns a number that isn't rounded (i.e 3x Item 2 should = 0.90 but it returns 0.8999999999999999).

cartReducer.js:

import Item1 from './images/apple_gala.jpg';
import Item2 from './images/apple_greenleaf.jpg'
import Item3 from './images/apple_granny.jpg'
import Item4 from './images/apple_pinklady.jpg'
import { ADD_TO_CART, REMOVE_ITEM } from '../actions/action-types/cart-actions.js'

const initState = {
    items: [
        {id:1,title:'Royal Gala', desc: "Gala apples have a blush of pink in their skin. It’s dense, sweet juicy flesh makes it ideal for eating fresh.", price:0.50, SKU:'A',img: Item1},
        {id:2,title:'Greenleaf', desc: "Our own original produce, the Greenleaf Original apple is award winning for the crispness of it's skin.",price:0.30, SKU:'B',img: Item2},
        {id:3,title:'Granny Smith', desc: "Our French Granny Smith apples have a distinct sharp taste – perfect for eating fresh or using in cooking.", price:0.20, SKU:'C',img: Item3},
        {id:4,title:'Pink Lady', desc: "A distinct and refreshing flavour with uniquely pink colouring - it can only be our Pink Lady apples.", price:0.15, SKU:'D',img: Item4},
    ],
    addedItems:[],
    total: 0

}
const cartReducer= (state = initState,action)=>{

    if(action.type === ADD_TO_CART){
          let addedItem = state.items.find(item=> item.id === action.id)

         let existed_item= state.addedItems.find(item=> action.id === item.id)
         if(existed_item)
         {
            addedItem.quantity += 1 
             return{
                ...state,
                 total: state.total + addedItem.price 
                  }
        }
         else{
            addedItem.quantity = 1;

            let newTotal = state.total + addedItem.price 

            return{
                ...state,
                addedItems: [...state.addedItems, addedItem],
                total : newTotal
            }

        }
    }
    if(action.type === REMOVE_ITEM){
        let itemToRemove= state.addedItems.find(item=> action.id === item.id)
        let new_items = state.addedItems.filter(item=> action.id !== item.id)

        let newTotal = state.total - (itemToRemove.price * itemToRemove.quantity )
        console.log(itemToRemove)
        return{
            ...state,
            addedItems: new_items,
            total: newTotal
        }
    }

  else{
    return state
    }

}

export default cartReducer

CartAjax.js:

import React, { Component } from 'react';
import { connect } from 'react-redux'
import { Link } from 'react-router-dom'
import Recipe from './Recipe.js'
import { removeItem,addQuantity,subtractQuantity} from './actions/cartActions'
import KeyboardArrowUpIcon from '@material-ui/icons/KeyboardArrowUp';
import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';
import ClearIcon from '@material-ui/icons/Clear';

class CartAjax extends Component {

    handleRemove = (id)=>{
        this.props.removeItem(id);
    }

    handleAddQuantity = (id)=>{
        this.props.addQuantity(id);
    }

    handleSubtractQuantity = (id)=>{
        this.props.subtractQuantity(id);
    }

    render(){

        let addedItems = this.props.items.length ?
            (  
                this.props.items.map(item=>{
                    return(

                        <li className="collection-item avatar" key={item.id}>
                            <div className="item-img"> 
                                <img src={item.img} alt={item.img} className=""/>
                            </div>

                            <div className="item-desc">
                                <li className="cart-ajax-left"><span className="title">{item.title}</span></li>
                                <li className="cart-ajax-left"><span className="price">Price: £{item.price}/pu</span><span className="SKU">SKU: {item.SKU}</span></li>
                                <p>
                                    <b>Quantity: {item.quantity}</b> 
                                </p>
                                <div className="add-remove">
                                    <Link to="/"><i className="material-icons" onClick={()=>{this.handleAddQuantity(item.id)}}><KeyboardArrowUpIcon/></i></Link>
                                    <Link to="/"><i className="material-icons" onClick={()=>{this.handleSubtractQuantity(item.id)}}><KeyboardArrowDownIcon/></i></Link>
                                </div>
                                <div className="remove-icon" onClick={()=>{this.handleRemove(item.id)}}><ClearIcon/></div>
                            </div>      
                        </li>
                    )
                })
            ):

             (
                <p>You must be hungry, order something...</p>
             )
       return(
            <div className="Cart-ajax">
                <div className="cart">
                    <h5>Your Order:</h5>
                    <ul className="collection cart-placeholder">
                        {addedItems}
                    </ul>
                </div> 
                <Recipe />
            </div>
       )
    }
}


const mapStateToProps = (state)=>{
    return{
        items: state.addedItems,
    }
}
const mapDispatchToProps = (dispatch)=>{
    return{
        removeItem: (id)=>{dispatch(removeItem(id))},
        addQuantity: (id)=>{dispatch(addQuantity(id))},
        subtractQuantity: (id)=>{dispatch(subtractQuantity(id))}
    }
}
export default connect(mapStateToProps,mapDispatchToProps)(CartAjax)

Recipe.js:

import React, { Component } from 'react'
import { connect } from 'react-redux'
//import { addShipping } from './actions/cartActions'
class Recipe extends Component{

    componentWillUnmount() {
         if(this.refs.shipping.checked)
              this.props.substractShipping()
    }

    handleChecked = (e)=>{
        if(e.target.checked){
            this.props.addShipping();
        }
        else{
            this.props.substractShipping();
        }
    }

    render(){

        return(
            <div className="container results">
                <div className="collection">
                    <li className="collection-item">
                        <span className="shipping">Excl. Shipping (£2.95)</span>
                    </li>
                        <li className="collection-item sub-total-value"><b>Order Total: £{this.props.total}</b></li>
                    </div>
                    <div className="checkout">
                        <button className="checkout-btn">Checkout</button>
                    </div>
                 </div>
        )
    }
}

const mapStateToProps = (state)=>{
    return{
        addedItems: state.addedItems,
        total: state.total
    }
}

const mapDispatchToProps = (dispatch)=>{
    return{
        addShipping: ()=>{dispatch({type: 'ADD_SHIPPING'})},
        substractShipping: ()=>{dispatch({type: 'SUB_SHIPPING'})}
    }
}

export default connect(mapStateToProps,mapDispatchToProps)(Recipe)

The cartReducer.js contains the price variables, these are rendered through Recipe.js which is included via <Recipe /> in the CartAjax.js file.

I am assuming I need a Math.round() type function. My question is can I achieve this in React.js and if so how?

van
  • 158
  • 1
  • 2
  • 12
  • Try this : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Number/toPrecision – Maifee Ul Asad Jun 07 '20 at 20:47
  • Does this answer your question? [Dealing with float precision in Javascript](https://stackoverflow.com/questions/11695618/dealing-with-float-precision-in-javascript) – Maifee Ul Asad Jun 07 '20 at 20:49
  • @MaifeeUlAsad not specifically for React, I knew I was looking for a Math.round function, it was the syntax that was wrong - see my below answer – van Jun 08 '20 at 15:41

2 Answers2

0
Math.round(your final value)

this can help you to achieve the result your expecting

check this out for further reference link

& react can't do this ideally

pageNotfoUnd
  • 666
  • 10
  • 20
0

Worked it out, you can use inline jS functions in React such as .toFixed(2) where (2) represents the number of decimal spaces. So in Recipe.js where the total value is called you can do:

<li className="collection-item sub-total-value"><b>Order Total: £{this.props.total.toFixed(2)}</b></li>

{this.props.total.toFixed(2)}
van
  • 158
  • 1
  • 2
  • 12