I made a page that contains products and they should add to the cart. But after connecting the backend from asp.net core to the products page, add to cart button is not working on the Product.js page.
TypeError: addCart is not a function onClick src/Component/section/Products.js:56 53 | </h3> 54 | <span>LKR {product.price}</span> 55 | <p>{product.description}</p> > 56 | <button onClick={()=> addCart(product.itemID)}>Add to cart</button> | ^ 57 | </div> 58 | </div> 59 | )) View compiled
context.js
import React, { Component } from 'react' export const DataContext = React.createContext(); export class DataProvider extends Component { state = { products: [ ], cart: [], total: 0 }; addCart = (id) =>{ const {products, cart} = this.state; const check = cart.every(item =>{ return item.itemID !== id }) if(check){ const data = products.filter(product =>{ return product.itemID === id }) this.setState({cart: [...cart,...data]}) }else{ alert("The product is already in the cart ") } }; reduction = id =>{ const { cart } = this.state; cart.forEach(item =>{ if(item.itemID === id){ item.count === 1 ? item.count = 1 : item.count -=1; } }) this.setState({cart: cart}); this.getTotal(); }; increase = id =>{ const { cart } = this.state; cart.forEach(item =>{ if(item.itemID === id){ item.count += 1; } }) this.setState({cart: cart}); this.getTotal(); }; removeProduct = id =>{ if(window.confirm("Do you want to delete this product?")){ const {cart} = this.state; cart.forEach((item, index) =>{ if(item.itemID === id){ cart.splice(index, 1) } }) this.setState({cart: cart}); this.getTotal(); } }; getTotal = ()=>{ const{cart} = this.state; const res = cart.reduce((prev, item) => { return prev + (item.price * item.count); },0) this.setState({total: res}) }; componentDidUpdate(){ localStorage.setItem('dataCart', JSON.stringify(this.state.cart)) localStorage.setItem('dataTotal', JSON.stringify(this.state.total)) }; componentDidMount(){ const dataCart = JSON.parse(localStorage.getItem('dataCart')); if(dataCart !== null){ this.setState({cart: dataCart}); } const dataTotal = JSON.parse(localStorage.getItem('dataTotal')); if(dataTotal !== null){ this.setState({total: dataTotal}); } } render() { const {products, cart,total} = this.state; const {addCart,reduction,increase,removeProduct,getTotal} = this; return ( <DataContext.Provider value={{products, addCart, cart, reduction,increase,removeProduct,total,getTotal}}> {this.props.children} </DataContext.Provider> ) } }
Products.js
import React, { Component } from 'react' import {Link} from 'react-router-dom' import {DataContext} from '../Context' import '../css/Products.css' import axios from 'axios'; export class Products extends Component { static contextType = DataContext; constructor(props) { super(props); this.state = { products: [] } } async componentDidMount() { try { const res = await axios.get('https://localhost:5001/api/Items'); console.log("he, he", res.data); this.setState({ products: res.data }); //this.state.products = res.data; console.log("uu", this.state.products); } catch (error) { console.log('er er', error) } } render() { const {products, addCart} = this.state; //const { products} = this.state; // const {addcart} =this; return ( <div id="product"> { products.map(product =>( <div className="card" key={product.itemID}> <Link to={`/product/${product.itemID}`}> <img src={`https://localhost:5001/${product.src}`} alt=""/> </Link> <div className="content"> <h3> <Link to={`/product/${product.itemID}`}>{product.title}</Link> </h3> <span>LKR {product.price}</span> <p>{product.description}</p> <button onClick={()=> addCart(product.itemID)}>Add to cart</button> </div> </div> )) } </div> ) } } export default Products;
Also there is a problem in this details.js page backend data is showing on console.But it does not displaying as a user interface in frontend.
Details.js
import React, { Component } from 'react' import {DataContext} from '../Context' import {Link} from 'react-router-dom' import Colors from './Colors' import '../css/Details.css' import axios from 'axios'; export class Details extends Component { static contextType = DataContext; constructor(props) { super(props); this.state = { products: [] } } async componentDidMount() { this.getProduct(); try { var id =this.props.match.params.id; const res = await axios.get(`https://localhost:5001/api/Items/${id}`); console.log("he, he", res.data); this.setState({ products: res.data }); this.state.products.id = res.data; console.log("uu", this.state.products.itemID); } catch (error) { console.log('er er', error) } } getProduct = () =>{ if(this.props.match.params.id){ const res = this.state.products; const data = res.filter(item =>{ return item.id === this.props.match.params.id }) this.setState({products: res.data}); this.state.products.id = res.data; } }; // componentDidMount(){ // this.getProduct(); // } // constructor(props) { // super(props); // this.state = { products: [] } // } render() { const {product} = this.state; // const {addCart} = this.context; return ( <> { product && product.length!=0 ? product.map(item =>( <div className="details" key={item.itemID}> <Link to={`/item/${item.itemID}`}> <img src={`https://localhost:5001/${item.src}`} alt=""/> </Link> <div className="box"> <div className="row"> <h2> <Link to={`/item/${item.itemID}`}>{item.title}</Link></h2> <span>LKR {item.price}</span> </div> {/* <Colors colors={item.colors}/> */} <p>{item.description}</p> <p>{item.content}</p> {/* <Link to="/cart" className="dcart" onClick={() => addCart(item.itemID)}> Add to cart </Link> */} </div> </div> )) :''} </> ) } } export default Details
Cart.js
import React, { Component } from 'react' import {DataContext} from '../Context' import {Link} from 'react-router-dom' import Colors from './Colors' import '../css/Details.css' import '../css/Cart.css' import { Button } from '../Button/Button' import StripeCheckout from 'react-stripe-checkout' import axios from 'axios'; import {toast} from 'react-toastify'; import GooglePayButton from '@google-pay/button-react'; export class Cart extends Component { static contextType = DataContext; componentDidMount(){ this.context.getTotal(); toast.configure(); } render() { const {cart,increase,reduction,removeProduct,total} = this.context; async function handleToken(token, addresses){ //console.log({token, addresses}) const response = await axios.post('https://iemcj.sse.codesandbox.io/checkout', { token, //item }); const {status} =response.data if (status === 'success'){ toast('Success! Check emails for details', {type: 'success'}) } else{ toast('Something went wrong', {type: 'error'}) } } if(cart.length === 0){ return <h2 style={{textAlign:"center"}}>Your Cart is Empty</h2> }else{ return ( <> { cart.map(item =>( <div className="details cart" key={`https://localhost:5001/${item.itemID}`}> <img src={`https://localhost:5001/${item.src}`} width="400" alt=""/> <div className="box"> <div className="row"> <h2>{item.title}</h2> <span>LKR {item.price * item.count}</span> </div> <Colors colors={item.colors}/> <h4>{item.description}</h4> <p>{item.content}</p> <div className="amount"> <button className="count" onClick={() => reduction(item.itemID)}> - </button> <span>{item.count}</span> <button className="count" onClick={() => increase(item.itemID)}> + </button> </div> </div> <div className="delete" onClick={() => removeProduct(item.itemID)}>X</div> </div> )) } <div className="total"> {/* <Link to="/checkout">Payment</Link> */} <GooglePayButton environment="TEST" paymentRequest={{ apiVersion:2, apiVersionMinor:0, allowedPaymentMethods: [ { type: 'CARD', parameters:{ allowedAuthMethods: ['CRYPTOGRAM_3DS', 'PAN_ONLY'], allowedCardNetworks: ['MASTERCARD', 'VISA'], }, tokenizationSpecification:{ type: 'PAYMENT_GATEWAY', parameters: { gateway: 'example', gatewayMerchantID: 'exampleGatewayMerchantID', }, }, }, ], merchantInfo: { merchantId: '12345678901234567890', merchantName:'Example Merchant', }, transactionInfo:{ totalPriceStatus:'FINAL', totalPriceLabel: 'Total', totalPrice:`${total}`, currencyCode:'LKR', countryCode:'LK', }, shippingAddressRequired:true, callbackIntents:['SHIPPING_ADDRESS','PAYMENT_AUTHORIZATION'], }} onLoadPaymentData={paymentRequest => { console.log('Success', paymentRequest); }} onPaymentAuthorized={paymentData => { console.log('Payment Authorised Success', paymentData) return { transactionState: 'SUCCESS'} }} onPaymentDataChanged={paymentData => { console.log('On Payment Data Changed', paymentData) return { } }} existingPaymentMethodRequired='false' buttonColor='black' buttonType='buy' /> <h3>Total: LKR {total}</h3> </div> </> ) } } } export default Cart
Section.js
import React, { Component } from 'react' import Products from './section/Products' import Details from './section/Details' import {Route} from "react-router-dom" import Cart from './section/Cart' import Payment from './section/Payment' import Confirmation from './Payment/Confirmation' import {Link} from 'react-router-dom' import '../Component/Section.css' class Section extends React.Component{ render(){ return( <div className="section"> <section> <Route path="/product" component={Products} exact /> <Route path="/product/:itemID" component={Details} exact /> <Route path="/cart" component={Cart} exact/> <Route path="/payment" component={Confirmation} exact /> </section> </div> ) } } export default Section
Advertisement
Answer
in Details.js this.setState({ products: res.data });
===> this.setState({ product: res.data });
.
and use condition:
{product && product.length!=0 ? product.map(product =>///your code) :'' }