I am trying to add items to a shopping cart. I have declared cart as an empty array and I am still getting the error:
TypeError: cart.map is not a function ProductContext.js:34
addItemToCart ProductContext.js:34
addItemHandler ProductCard.js:47
onClick ProductCard.js:60
Here is my context:
// ProductContext.js
import React, { createContext, useState } from "react"
import { graphql, useStaticQuery } from "gatsby"
const ProductContext = createContext({
cart: [],
addItem: () => {}
})
const Provider = ({ children }) => {
const [cart, setCart] = useState([]);
const [productsList] = useState(
useStaticQuery(
graphql`
query SkusForProduct {
skus: allStripeSku(sort: { fields: [price] }) {
edges {
node {
id
currency
price
attributes {
name
}
}
}
}
}
`
)
)
const addItemToCart = skuId => {
let itemExisted = false
let updatedCart = cart.map(item => {
if (skuId === item.sku) {
itemExisted = true
return { sku: item.sku, quantity: ++item.quantity }
} else {
return item
}
})
if (!itemExisted) {
updatedCart = [...updatedCart, { sku: skuId, quantity: 1 }]
}
setCart({ cart: updatedCart })
localStorage.setItem('stripe_checkout_items', JSON.stringify(updatedCart))
}
return (
<ProductContext.Provider value={{ skus: productsList.skus, addItem: addItemToCart }}>
{children}
</ProductContext.Provider>
)
}
export { ProductContext, Provider }
And my ProductCard
// ProductCard.js
import React, { useState, useContext } from "react"
import { ProductContext } from "../context/ProductContext"
const cardStyles = {
display: "flex",
flexDirection: "column",
justifyContent: "space-around",
alignItems: "flex-start",
padding: "1rem",
marginBottom: "1rem",
boxShadow: "5px 5px 25px 0 rgba(46,61,73,.2)",
backgroundColor: "#fff",
borderRadius: "6px",
maxWidth: "300px",
}
const buttonStyles = {
fontSize: "13px",
textAlign: "center",
color: "#fff",
outline: "none",
padding: "12px",
boxShadow: "2px 5px 10px rgba(0,0,0,.1)",
backgroundColor: "rgb(255, 178, 56)",
borderRadius: "6px",
letterSpacing: "1.5px",
}
const formatPrice = (amount, currency) => {
let price = (amount / 100).toFixed(2)
let numberFormat = new Intl.NumberFormat(["en-US"], {
style: "currency",
currency: currency,
currencyDisplay: "symbol",
})
return numberFormat.format(price)
}
const ProductCard = () => {
const [disabled] = useState(false)
const [buttonText, setButtonText] = useState("Add to Cart")
const [paymentMessage, setPaymentMessage] = useState("")
const skus = useContext(ProductContext).skus
const addItem = useContext(ProductContext).addItem
const addItemHandler = (event, skuId, quantity = 1) => {
addItem(skuId);
}
return (
<div>
{skus.edges.map(({ node: sku }) => {
return (
<div style={cardStyles} key={sku.id}>
<h4>{sku.attributes.name}</h4>
<p>Price: {formatPrice(sku.price, sku.currency)}</p>
<button
style={buttonStyles}
onClick={event => addItemHandler(event, sku.id)}
disabled={disabled}
>
{buttonText}
</button>
{paymentMessage}
</div>
)
})}
</div>
)
}
export default ProductCard
I have logged the output of cart in the addItemToCart function and I get an empty array. Not sure what I've done wrong. Any help would be greatly appreciated!
cartis a constant with no valuecartalways stays as anarray? In theProvider, right before you do thereturn, if youconsole.log(cart)does it ever change to anything else?mapmethod should work just fine. It sounds like he's accidentally changing his state to something else other thanarray.{…} cart: (1) […] 0: {…} quantity: 1 sku: "sku_Gi0Yhgc3z0xz37"But when I try to add another item I get the same error. Am I changing the array to an object somehow?console.log(updatedCart)right beforesetCart({ cart: updatedCart }), isupdatedCartalways anarray?