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?