Who can I call the function only if - reactjs

Hey guys I need your help. I want to call a function but only if other function works. But I can't do that unfortunately, could you help me?
Here's my code:
'use strict';
import React from 'react/addons';
import { Carousel, CarouselItem } from 'react-bootstrap';
import { Link } from 'react-router';
import cx from 'classnames';
import { user as userAccount } from '../../scripts/account-details';
function getColorForChannel(name) {
const hue = Array.from(name)
.map((ch, i) => ch.charCodeAt(0) * (i + 1))
.reduce((sum, ch) => sum + ch, 0) % 360;
return `hsl(${hue}, 75%, 75%)`;
}
function urlify(text){
var urlRegex = /(https?:\/\/[^\s]+)?\.(com|pt|es|org|net|)?/g;
return urlRegex.test(text);
}
function parseLinha(linha) {
return linha.split(' ')
.map((x, i) => urlify(x) ? <a key={i} href={x.trim()} target='_blank' rel='nofollow'>{x} </a> : x + " ");
}
/**
* Usernames that don't really link to people.
*/
const nonPeopleUserNames = ['linsasupport'];
const TimelineItem = React.createClass({
getDefaultProps() {
return {
important: false
};
},
propTypes: {
routeDepth: React.PropTypes.number,
router: React.PropTypes.func,
item: React.PropTypes.object.isRequired,
onDelete: React.PropTypes.func,
onLinkClicked: React.PropTypes.func.isRequired,
important: React.PropTypes.bool
},
getChildContext() {
return {
routeDepth: this.props.routeDepth,
router: this.props.router
};
},
childContextTypes: {
routeDepth: React.PropTypes.number.isRequired,
router: React.PropTypes.func.isRequired
},
getUrlState() {
return (
<div class="row">
<div class="col-sm-6 col-md-4">
<div class="thumbnail">
<img src="..." alt="..."/>
<div class="caption">
<h3>Thumbnail label</h3>
<p>...</p>
<p>Button Button</p>
</div>
</div>
</div>
</div>
);
},
renderAttachments(attachments) {
if (!attachments.length) { return null; }
if (attachments.every((a) => a.Type.toLowerCase() === 'image')) {
return (
<Carousel>
{attachments.map((a) =>
<CarouselItem key={a.Id}>
<a href={`timeline/${this.props.item.Id}/attachments/${a.Id}`} target='_blank'>
<div style={{
backgroundImage: `url(/timeline/${this.props.item.Id}/attachments/${a.Id})`,
backgroundSize: 'contain',
backgroundPosition: 'center center',
height: 300, width: '100%', backgroundRepeat: 'no-repeat' }} />
</a>
</CarouselItem>)}
</Carousel>
);
}
return (
<div className='si-timeline-item-attachments'>
<ul className='fa-ul'>
{attachments.map((a) =>
<li key={a.Id}>
<i className='fa-li fa fa-file' />
<a href={`/timeline/${this.props.item.Id}/attachments/${a.Id}`}
target='_blank'>
{a.Name}
</a>
</li>)}
</ul>
</div>
);
},
handleDelete() {
if (typeof (this.props.onDelete) === 'function') {
this.props.onDelete();
}
},
render() {
const { item, important } = this.props;
const itemClasses = cx({
'si-timeline-item': true,
'si-urgent': important
});
const d = item.Date instanceof Date ? item.Date : new Date(item.Date);
return (
<div className={itemClasses}>
<div className='si-timeline-item-header'>
{important ?
<button className='btn btn-default si-delete-btn'
onClick={this.handleDelete}
title='Remover notificação'>
<i className='fa fa-lg fa-remove' />
</button> : null}
<div className='si-profile-image-fixed'
style={{
backgroundImage: `url(/users/${item.Author.UserName}/profileimage)`
}} />
<div>
{nonPeopleUserNames.indexOf(item.Author.UserName) === -1 ?
<Link className='si-timeline-item-title-fixed'
onClick={(e) => this.props.onLinkClicked(e)}
to={`/users/${item.Author.UserName}`}>
{item.Author.Name} {item.Author.UserName === userAccount.manager ? <small>(Manager)</small> : null}
</Link> :
<span className='si-timeline-item-title-fixed'>
{item.Author.Name} {item.Author.UserName === userAccount.manager ? <small>(Manager)</small> : null}
</span>}
<date className='si-timeline-item-date-fixed' dateTime={d.toISOString()}>
{d.toLocaleString(navigator.language)}
</date>
</div>
<small className='si-timeline-item-channel'
style={{borderRight: `7px solid ${getColorForChannel(item.Channel.Name)}`}}>
{item.Channel.Name}
</small>
</div>
<div className='si-timeline-item-content'>
{item.Contents.split('/n')
.map((l, i) => {
const conteudos = parseLinha(l);
console.log(conteudos);
return <p key={i}>{conteudos}</p>;
})}
{this.getUrlState()}
</div>
{this.renderAttachments(item.Attachments)}
</div>
);
}
});
export default TimelineItem;
Here's the function :
function urlify(text){
var urlRegex = /(https?:\/\/[^\s]+)?\.(com|pt|es|org|net|)?/g;
return urlRegex.test(text);
And here's the function I want to call only if function urlify happens:
getUrlState() {
return (
<div class="row">
<div class="col-sm-6 col-md-4">
<div class="thumbnail">
<img src="..." alt="..."/>
<div class="caption">
<h3>Thumbnail label</h3>
<p>...</p>
<p>Button Button</p>
</div>
</div>
</div>
</div>
);
},
Really need your help thanks.

Related

how to add data in localstorage in react

I am arslan Chaudhry. currently, I am working on an eCommerce site where I will store data in local storage because I don't have too much backend knowledge. how I can add functionality like delete and update on another folder.
my code is given below.
Books.js
import React from "react";
import "./components/book.css";
import Carousel from "react-multi-carousel";
import "react-multi-carousel/lib/styles.css";
import { FaShoppingCart } from "react-icons/fa";
import { useEffect } from "react";
import { useState, useRef } from "react";
import { useNavigate } from "react-router-dom";
import { createContext } from "react";
const Books = () => {
let arr=()=>{
let dat=localStorage.getItem("products")
if (dat) {
return JSON.parse(dat)
}
else{
return []
}
}
const [booksData, setbooksData] = useState([]);
const [productData, setproductData] = useState(arr());
let nav = useNavigate();
// slider
const responsive = {
superLargeDesktop: {
breakpoint: { max: 4000, min: 3000 },
items: 5,
},
desktop: {
breakpoint: { max: 3000, min: 1024 },
items: 3,
},
tablet: {
breakpoint: { max: 1024, min: 464 },
items: 2,
},
mobile: {
breakpoint: { max: 464, min: 0 },
items: 1,
},
};
let croser = useRef("");
let loding = useRef("");
const getJason = async () => {
try {
let fea = await fetch(
"https://script.google.com/macros/s/AKfycbxFCG7S-kjncQZwvcMnqq4wXoBAX8ecH1zkY2bLP7EE-YHlnKbiJ3RUuHtWLe6sIK30Kw/exec"
);
let acData = await fea.json();
let itemsData = acData.shop.filter((element) => {
if (element.name) {
return element;
}
});
setbooksData(itemsData);
if (itemsData) {
croser.current.style.filter = "blur(0px)";
loding.current.style.display = "none";
}
} catch (error) {
croser.current.style.filter = "blur(0px)";
loding.current.style.display = "none";
}
};
// get product data from api
useEffect(() => {
getJason();
}, []);
// go to cart button
const goto = () => {
nav("/Cart");
};
// local data
let addNow=(e)=>{
let data=productData.find((element)=>{return element.id === e.id });
let cart;
if (data) {
cart=productData.map((element)=>{
return element.id === e.id ? {...element, quantity:element.quantity+1}:element
})
}
else{
cart=[...productData,{...e, quantity:1}]
}
setproductData(cart);
};
useEffect(() => {
localStorage.setItem("products",JSON.stringify(productData))
}, [productData])
console.log(productData);
return (
<>
<div className="row " style={{ marginTop: "10px" }}>
<div className="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<div className="section-headline text-center">
<h2>Books Shop</h2>
</div>
</div>
</div>
<div className="lodingBooks" ref={loding}>
<div class="spinner-border" role="status"></div>
<h4>Please wait....</h4>
</div>
<div ref={croser}>
<div className=" shadow go_to_cart" onClick={goto}>
<i class="bi bi-cart-check text-white"></i>
</div>
<Carousel responsive={responsive} className="container">
{booksData.map((element) => {
return (
<>
<div class="container page-wrapper">
<div class="page-inner">
<div class="row">
<div class="el-wrapper">
<div class="box-up">
<img class="img" src={element.images} alt="" />
<div class="img-info">
<div class="info-inner">
<span class="p-name text-info">
{element.name}
</span>
<span class="p-company ">Author:CHAUDHRY</span>
</div>
<div class="a-size ">
About:This is a complete book on javascript
<span class="size"></span>
</div>
</div>
</div>
<input
type="text"
value={1}
style={{ display: "none" }}
/>
<div class="box-down">
<div class="h-bg">
<div class="h-bg-inner"></div>
</div>
<a class="cart">
<span class="price">{element.price + "$"}</span>
<span
class="add-to-cart btn btn-sm"
style={{ backgroundColor: "#3EC1D5" }}
onClick={()=>{addNow(element)}}
>
<span class="txt">
ADD TO CART <FaShoppingCart />
</span>
</span>
</a>
</div>
</div>
</div>
</div>
</div>
</>
);
})}
</Carousel>
</div>
</>
);
};
export default Books;
and here is my cart file. where i want to perform the action like update and delete.
Cart.js
import React from "react";
import "./components/cart.css";
import { useEffect } from "react";
const Cart = () => {
let data = localStorage.getItem("products");
let javaData = JSON.parse(data);
let removeData = (e) => {
};
useEffect(() => {
localStorage.clear()
}, [])
return (
<>
<div class="container mt-5 mb-5">
<div class="d-flex justify-content-center row">
<div class="col-md-8">
<div class="p-2 shoingTitle">
<h4>Shop Now</h4>
<span class="text-danger">Remove all</span>
</div>
{javaData ? (
javaData.map((item) => {
return (
<>
<div class="d-flex flex-row justify-content-between align-items-center p-2 bg-white mt-4 px-3 rounded">
<div class="mr-1 imageandpara">
<img class="rounded" src={item.images} width="70" />
<span class="font-weight-bold">{item.name}</span>
</div>
<div class="d-flex flex-column align-items-center product-details">
<div class="d-flex flex-row product-desc"></div>
</div>
<div class="d-flex flex-row align-items-center qty">
<i class="minusSign shadow">
<i class="bi bi-dash"></i>
</i>
<span class="text-grey quantityNumber">
{item.quantity}
</span>
<i class="minusSign shadow">
<i class="bi bi-plus"></i>
</i>
</div>
<div>
<span class="text-grey productAmount">{`${
item.quantity * item.price
}$`}</span>
</div>
<div
class="d-flex align-items-center text-dark "
style={{
cursor: "pointer",
fontWeight: "900",
fontSize: "15px",
}}
onClick={() => {
removeData(item);
}}
>
<i class="bi bi-x text-danger"></i>
</div>
</div>
</>
);
})
) : (
<h3 style={{ textAlign: "center" }}>Cart is empety</h3>
)}
<div class="d-flex flex-row align-items-center mt-3 p-2 bg-white rounded">
<input
type="text"
class="form-control gift-card "
placeholder="discount code/gift card"
/>
<button
class="btn btn-sm ml-3 shadow"
type="button"
style={{
outline: "#3EC1D5",
backgroundColor: "#3EC1D5",
color: "white",
}}
>
Apply
</button>
</div>
<div class="totalItems">
Total Items: <strong>12</strong>
</div>
<span class="TotalPrice">
Total price: <strong>12$</strong>
</span>
<div class="d-flex flex-row align-items-center mt-3 p-2 bg-white rounded">
<button
class="btn btn-block btn-sm ml-2 pay-button shadow"
type="button"
style={{ backgroundColor: "#3EC1D5" }}
>
Proceed to Pay
</button>
</div>
</div>
</div>
</div>
</>
);
};
export default Cart;
Try this for add:
let removeData = (e) => {
localStorage.setItem("name of the item") // e.target.name
};
There's alot going on in your site :)
I think it will be responsible to create a context, that will serve the cart to all other components.
Things to note here, (Found some little improvements)
Run the function in the useState hook, don't just leave it there like you did
When using Array.filter you need to return a boolean iorder for it too filter your array properly.
This is the code I brought up hope it helps you out.
CartContext.js file.
import React, { createContext, useContext, useEffect, useState } from "react";
export const CartContext = createContext();
function Cart({ children }) {
const arr = useCallback(() => {
let dat = localStorage.getItem("products");
if (dat) {
return JSON.parse(dat);
} else {
return [];
}
}, []);
const [productData, setproductData] = useState(() => arr());
const getJason = async () => {
try {
let fea = await fetch(
"https://script.google.com/macros/s/AKfycbxFCG7S-kjncQZwvcMnqq4wXoBAX8ecH1zkY2bLP7EE-YHlnKbiJ3RUuHtWLe6sIK30Kw/exec"
);
let acData = await fea.json();
// filter callback function should return a boolean. That is either true or false in order to make it work.
// SO i think this function isn't going to function properly
let itemsData = acData.shop.filter((element) => {
if (element.name) {
return element;
}
});
setbooksData(itemsData);
if (itemsData) {
croser.current.style.filter = "blur(0px)";
loding.current.style.display = "none";
}
} catch (error) {
croser.current.style.filter = "blur(0px)";
loding.current.style.display = "none";
}
};
// get product data from api
useEffect(() => {
getJason();
}, []);
const addProduct = (e) => {
// check if product id available on cart
const findProduct = productData.find((element) => {
return element.id === e.id;
});
// add first quantity if not available
if (!findProduct)
return setproductData([...productData, { ...e, quantity: 1 }]);
// increase quantity by 1
const newCart = productData.map((element) => {
return {
...element,
quantity: element.id === e.id ? element.quantity + 1 : element.quantity,
};
});
setproductData(newCart);
};
const removeProduct = (e) => {
// check if product id available on cart
const findProductQuantity = productData.find((element) => {
return element.id === e.id && element.quantity >= 1;
});
// add first quantity if not available
if (!findProduct)
// Your ui should prevent this
return;
// decrease quantity by 1
const reducedQuantityCart = productData.map((element) => {
return {
...element,
quantity: element.id === e.id ? element.quantity - 1 : element.quantity,
};
});
// filter out all products with quantity less than 1 (quantity : 0)
const newCart = productData.filter((element) => {
return element.quantity >= 1;
});
setproductData(newCart);
};
const deleteProduct = (e) => {
// check if product id available on cart
const findProduct = productData.find((element) => {
return element.id === e.id;
});
// add first quantity if not available
if (!findProduct)
// Your ui should prevent this
return;
const productIndex = productData.findIndex((element) => {
return element.id === e.id;
});
// splice (delete) product from the productData array
const newCart = [productData].splice(productIndex, 1);
setproductData(newCart);
};
const value = {
productData,
addProduct,
removeProduct,
deleteProduct,
};
return <CartContext.Provider value={value}>{children}</CartContext.Provider>;
}
In here you create a context, create all your function you will use to update your cart, and pass them to your Context provider
// create a hook can you use anywhere in the app
export const useCart = () => {
const context = useContext(CartContext);
if (!context) {
throw new Error("Must use useCart in CartContext Child");
}
const { productData, addProduct, removeProduct, deleteProduct } = context;
return { productData, addProduct, removeProduct, deleteProduct };
};
For this you create a custom hook that you can use inside any component provided it is a child of the Cart context. So make sure you wrap it all around your app
// Use Case
const SomeComponent = () => {
const { productData, addProduct, removeProduct } = useCart();
return (
<div>
<p> Number of Products: {productData.length}</p>
<div>
{productData?.map((product) => (
<div>
<p>{product?.name}</p>
<button onClick={() => addProduct(product)}>add</button>
<button onClick={() => removeProduct(product)}>
subtract/reduce
</button>
<button onClick={() => deleteProduct(product)}>delete</button>
</div>
))}
</div>
</div>
);
};
Use case Scenario od how this code will work. Hope you find this helful

React JS State late Update

I recently started doing React JS but facing one Problem. I use
bootstrap flat icons in my component. I have two APIs one for the
product list and the second for the wish list I have to compare both
API results. if the product is present in the wishlist then I have to
show the heart icon filled if not then unfilled. But I am facing an
issue in that I create the logic for comparing them and then push in
the state but it renders the product list first but does not show the
icons filled. But if I make any changes in the component & save them
crtl+s then show the icons filled. means it updates the state early.
I did not find any solution to this.
import React, { useEffect, useState } from 'react';
import { product } from '../../../_services';
import "../../../_UI/slick-carousel/slick/slick.css";
import "../../../_UI/slick-carousel/slick/slick-theme.css";
import { Link } from 'react-router-dom';
import { useHistory } from 'react-router-dom'
import Slider from "react-slick";
import { useDispatch,useSelector} from 'react-redux';
import { CartActions,wishlistActions } from '../../../_actions';
function NewArrival() {
const selector = useSelector((state)=>state);
const dispatch = useDispatch();
const [value, setvalue] = useState([]);
const [value2, setvalue2] = useState([]);
const settingSlider = {
dots: true,
slidesToShow: 4,
slidesToScroll: 4,
autoplay: true,
autoplaySpeed: 5000,
Speed:10,
pauseOnHover:true,
arrows: false,
responsive: [
{
breakpoint: 1024,
settings: {
slidesToShow: 3,
slidesToScroll: 3,
infinite: true,
}
},
{
breakpoint: 600,
settings: {
slidesToShow: 2,
slidesToScroll: 2,
infinite: true,
}
},
{
breakpoint: 480,
settings: {
slidesToShow: 1,
slidesToScroll: 1,
infinite: true,
}
}
]
}
const AddToWishList = (sku_name)=>{
dispatch(wishlistActions.AddToWishListRequested(sku_name))
}
const AddToCart = async (sku,index) => {
const user_id = localStorage.getItem('card_id');
let product_details = {
sku_name: sku,
qty: 1,
quote_id: user_id
}
dispatch(CartActions.ADDCARTREQUEST(product_details,index));
}
useEffect(() => {
newArrivalApi()
}, [])
async function newArrivalApi(){
if(localStorage.getItem('user')){
const result = await product.ProductsNewarrival(39);
const result2 = await product.ProductsNewarrival(71)
console.log(selector.WishListProcess.wishlist);
//compare logic
result2.data.items?.map((items,index)=>{
selector?.WishListProcess?.wishlist?.map((item)=>{
if(items.id==item.product_id){
result2.data.items.push({...items,wishlist:true})
result2.data.items.splice(index,1);
}
})
})
//compare logic second slider
result.data.items?.map((items,index)=>{
selector?.WishListProcess?.wishlist?.map((item)=>{
if(items.id==item.product_id){
result.data.items.push({...items,wishlist:true})
result.data.items.splice(index,1);
}
})
})
// console.log(result.data.items);
// console.log(result2.data.items);
setvalue(result?.data?.items);
setvalue2(result2?.data?.items)
}
else{
const result = await product.ProductsNewarrival(39);
const result2 = await product.ProductsNewarrival(71)
console.log(result)
console.log(result2);
setvalue2(result2.data.items)
setvalue(result.data.items)
}
}
return (
<>
<section className="collection-section">
{value?.length > 0 ?
<div className="container-fluid">
<div className="text-center my-5">
<h3 className="heading-text">
New Arrival
</h3>
<h4 className="sub-heading-text">
"Fashion Fade. Style is eternal."
</h4>
</div>
<div className="row align-items-lg-center">
<div className="col-lg-9 col-md-9">
<div className="row justify-content-lg-between justify-content-center" >
<div className="col-lg-12">
<Slider {...settingSlider}>
{value.map((item, index) => {
return (
<div key={index} >
<div className="product-info">
<div className="product-image">
<Link to={"/product_details/" + item.sku} > <img src={item?.custom_attributes[0].attribute_code ==="image" ? item.custom_attributes[0].value : item.custom_attributes[1].value } alt='' className="img-fluid" /></Link>
</div>
<div className="product-title"><a href={"/product_details/" + item.sku}>{item.name}</a></div>
<div className="product-price">${item.price}</div>
<div className="add-wishlist-out">
<div className="add-to-cart-outer">
<button onClick={()=>{AddToCart(item.sku,item.id)}} className="add-to-cart-btn"><i className="fa fa-solid fa-cart-shopping"></i>{selector?.CartProcess?.loading === true && selector?.CartProcess?.index === item.id ? "LOADING..." : "Add to cart"}</button>
</div>
<div className="wishlist-out">
<a onClick={()=>{AddToWishList(item.sku)}} className="wishlist-icon"><i className={item.wishlist===true ? "fa fa-solid fa-heart" :"far fa-heart"}></i></a>
<i className="fa fa-solid fa-signal"></i>
</div>
</div>
</div>
</div>
)})}
</Slider>
</div>
</div>
</div>
<div className="col-lg-3 col-md-3">
<div className="long-img">
<img src="./assets/images/1608b80571524e822b386e9da05f02f2.jpg" className="img-fluid" />
</div>
</div>
</div>
<div className="row align-items-lg-center">
<div className="col-lg-3 col-md-3">
<div className="long-img">
<img src="./assets/images/ww8.jpg" className="img-fluid" />
</div>
</div>
<div className="col-lg-9 col-md-9">
<div className="row justify-content-lg-between justify-content-center" >
<div className="col-lg-12" >
<Slider {...settingSlider} >
{value2.map((item, index) => {
return (
<div key={index} >
<div className="product-info">
<div className="product-image">
<a href={'/product_details/' + item.sku} ><img src={item?.custom_attributes[0].attribute_code ==="image" ? item.custom_attributes[0].value : item.custom_attributes[1].value } alt='' className="img-fluid" /></a>
</div>
<div className="product-title"><a href={"/product_details/" + item.sku}>{item.name}</a></div>
<div className="product-price">${item.price}</div>
<div className="add-wishlist-out">
<div className="add-to-cart-outer">
<button onClick={()=>{AddToCart(item.sku,item.id)}} className="add-to-cart-btn"><i className="fa fa-solid fa-cart-shopping"></i>{selector?.CartProcess?.loading === true && selector?.CartProcess?.index === item.id ? "LOADING..." : "Add to cart"}</button>
</div>
<div className="wishlist-out">
<a onClick={()=>{AddToWishList(item.sku)}} className="wishlist-icon"><i className={item.wishlist===true ? "fa fa-solid fa-heart" :"far fa-heart"}></i></a>
<i className="fa fa-solid fa-signal"></i>
</div>
</div>
</div>
</div>
)})}
</Slider>
</div>
</div>
</div>
</div>
</div>
: " "}
</section>
</>
)
}
export { NewArrival };
That is the normal behavior of useState because useState is async function so it takes a little bit of time to set the state before use it so you have to find a way around to use it, I suggest why are you setting two set one state and inside its object like this:
const [valueState, setValueState] = React.useState({ result: [], result2: [] });
setValueState({ result: result?.data?.items, result2: result2?.data?.items });
and use it like this
valueState?.result
valueState?.result2

Cannot add item to cart when click on the button

When i click on the cart symbol, it changes its value to be in cart but actually my product is not rendered on the cart component, is there something wrong or missing in my code, please help me to fix it! Thank you so much!
Context.js:
class ProductProvider extends React.Component {
state = {
products: storeProducts,
detailProduct: detailProduct,
cart: [],
modalOpen: false,
modalProduct: detailProduct
};
getItem = (id) => {
const product = this.state.products.find((item) => item.id === id);
return product;
};
addToCart = (id) => {
console.log("add to cart");
let tempProducts = [...this.state.products];
const index = tempProducts.indexOf(this.getItem(id));
const product = tempProducts[index];
product.inCart = true;
product.count = 1;
const price = product.price;
product.total = price;
this.setState(() => {
return (
{ products: tempProducts, cart: [...this.state.cart, product] },
() => console.log(this.state)
);
});
};
openModal = (id) => {
const product = this.getItem(id);
this.setState(() => {
return { modalProduct: product, openModal: true };
});
};
closeModal = (id) => {
this.setState(() => {
return { modalOpen: false };
});
};
Cart.js:
import React from "react";
import CartColumns from "./CartColumns";
import CartList from "./CartList";
import EmptyCart from "./EmptyCart";
import { ProductContext } from "../App";
export default class Cart extends React.Component {
render() {
return (
<div>
<ProductContext.Consumer>
{(value) => {
console.log(value, "inside Product COnt");
if (value.length > 0) {
return (
<div>
<CartColumns />
<CartList items={items} />
</div>
);
} else {
<EmptyCart />;
}
}}
</ProductContext.Consumer>
</div>
);
}
}
CartList.js:
import React from "react";
import CartItem from "./CartItem";
export default function CartList(props) {
const { items } = props;
return (
<div>
{items.cart.map((item) => (
<CartItem
key={item.id}
item={item}
increment={item.increment}
decrement={item.decrement}
/>
))}
</div>
);
}
CartItem.js:
import React from "react";
function CartItem(props) {
const { id, title, img, price, total, count } = props.item;
const { increment, decrement, removeItem } = props;
return (
<div className="row my-1 text-capitalize text-center">
<div className="col-10 mx-auto col-lg-2">
<img
src={img}
style={{ width: "5rem", heigth: "5rem" }}
className="img-fluid"
alt=""
/>
</div>
<div className="col-10 mx-auto col-lg-2 ">
<span className="d-lg-none">product :</span> {title}
</div>
<div className="col-10 mx-auto col-lg-2 ">
<strong>
<span className="d-lg-none">price :</span> ${price}
</strong>
</div>
<div className="col-10 mx-auto col-lg-2 my-2 my-lg-0 ">
<div className="d-flex justify-content-center">
<div>
<span className="btn btn-black mx-1">-</span>
<span className="btn btn-black mx-1">{count}</span>
<span className="btn btn-black mx-1">+</span>
</div>
</div>
</div>
<div className="col-10 mx-auto col-lg-2 ">
<div className=" cart-icon">
<i className="fas fa-trash" />
</div>
</div>
<div className="col-10 mx-auto col-lg-2 ">
<strong>item total : ${total} </strong>
</div>
</div>
);
}
export default CartItem;
Sandbox link for better observation:https://codesandbox.io/s/cart-code-addict-forked-l6tfm?file=/src/cart/CartItem.js
There were few issues
Change following
this.setState(() => {
return (
{ products: tempProducts, cart: [...this.state.cart, product] },
() => console.log(this.state)
);
});
to
this.setState(
{
products: tempProducts,
cart: [...this.state.cart, product]
},
() => console.log(this.state)
);
And need to use value.cart to check for length and when passing as a prop.
Instead of
if (value.length > 0) {
return (
<div>
<CartColumns />
<CartList items={items} />
</div>
);
}
It should be
if (value.cart.length > 0) {
return (
<div>
<CartColumns />
<CartList items={value.cart} />
</div>
);
}
And in CartList,
Instead of
{
items.cart.map(item => (
<CartItem
key={item.id}
item={item}
increment={item.increment}
decrement={item.decrement}
/>
));
}
it should be
{
items.map(item => (
<CartItem
key={item.id}
item={item}
increment={item.increment}
decrement={item.decrement}
/>
));
}
Now it shows the cart with items
Code sandbox => https://codesandbox.io/s/cart-code-addict-forked-c3kug?file=/src/cart/CartList.js

Cannot define properties of undefined

I am having an issue with my skillImage components.
I am not sure where the issue is coming from.
I get error message cannot read properties of undefined : id but it has been destructured correctly.
I have put below the following components involved, SkillContext, Skill, SkillsList.
The line of code in question is const { skillCard: {id, skill} } = useContext(SkillContext);
Can someone tell me what is wrong, please?
Thanks in advance
skill.js
import Image from "next/dist/client/image";
import { FaTimes, FaRegCalendarAlt, FaSchool,FaSpinner } from "react-icons/fa";
import styles from '../../styles/Home.module.scss'
//import { FaStar } from 'react-icons/fa';
import { AiFillStar , AiOutlineStar } from 'react-icons/ai'
import { useState, useContext } from 'react';
import { CourseFilterContext } from "../contexts/CourseFilterContext";
import { SkillProvider, SkillContext } from "../contexts/SkillContext";
function Course({ courseTitle, hours, level, year }) {
return (
<>
<span className={styles.course}>
<strong>Course :</strong> {courseTitle}{" "}
</span>
<span className={styles.course}>
<strong>Hours: </strong> {hours}
</span>
<span className={styles.course}>
<strong>Level :</strong> {level}
</span>
<span className={styles.course}>
<strong>Year :</strong> {year}
</span>
</>
);
}
function Courses() {
const { courseYear } = useContext(CourseFilterContext);
const { skillCard } = useContext(SkillContext);
const courses = skillCard.courses;
const level = skillCard.level;
return (
<div className={styles.courseBox, "h-250"}>
{courses
.filter(function (course) {
return course.year === courseYear;
})
.map(function (course) {
return (
<Course {...course} level={level} key={skillCard.courses.id} />
)
})
}
</div>
);
}
function SkillImage() {
const { skillCard: {id, skill} } = useContext(SkillContext);
,
return (
<div className="speaker-img d-flex flex-row justify-content-center align-items-center h-300">
<Image
src={`/images/skill-${id}.png`}
className="contain-fit"
alt={`${skill}`}
width="300"
height="300"
/>
</div>
);
}
function SkillFavorite () {
const { skillCard, updateRecord } = useContext(SkillContext);
const [inTransition, setInTransition] = useState(false);
function doneCallBack () {
setInTransition(false);
console.log(`In SkillFavorite: doneCallBack ${new Date().getMilliseconds()}`)
}
return (
<div className={styles.icon}>
<span onClick={function () {
setInTransition(true);
updateRecord(
{
...skillCard, favorite: !skillCard.favorite,
},
doneCallBack
)
}}>
{ skillCard.favorite === false ?
<AiFillStar fill="orange"/> : <AiOutlineStar fill="yellow"/>
}{" "}
Favorite{" "}
{ inTransition === true ? (
<span><FaSpinner className="fa-spin" fill="orange"/></span>
): null}
</span>
</div>
)
}
function SkillDescription() {
const { skillCard } = useContext(SkillContext);
const { skill, description, school, } = skillCard;
return (
<div>
<h3 className="text-truncate text-justify w-200">
{skill}
</h3>
<SkillFavorite />
<p className="text-justify skill-info">{description}</p>
<div className="social d-flex flex-row mt-4 justify-content-between">
<div className="school mb-2">
{/* <FaSchool className="m-3 align-middle " fill="#000"/> */}
<h5>School</h5>
<h6>{school}</h6>
</div>
<div className="calendar mb-2">
{/* <FaRegCalendarAlt className="m-3 align-middle " fill="#000"/> */}
{/* <h5>Year</h5>
<h6>{courses[0].year}</h6> */}
</div>
</div>
</div>
);
}
function SkillAction () {
return (
<div className="row mb-2">
<button
className="btn btn-primary w-100"
onClick={() => handleEditClick()}
>Edit
</button>
<div className="row mt-2">
<FaTimes className="m-3 " fill="#ffc800" onClick={() => handleDeleteClick(idx)} />
</div>
</div>
);
}
function Skill({ skillCard, updateRecord, insertRecord, deleteRecord }) {
const { showCourses } = useContext(CourseFilterContext);
return (
<SkillProvider skillCard={skillCard} updateRecord={updateRecord} insertRecord={insertRecord} deleteRecord={deleteRecord}>
<div className="col-xs-12 col-sm-12 col-md-6 col-lg-4 col-sm-12 col-xs-12">
<div className="card card-height p-4 mt-4 mb-2 h-300">
<SkillImage />
<div className="card-body">
<SkillDescription />
{showCourses === true ?
<Courses /> : null}
</div>
<div className="card-footer">
<SkillAction />
</div>
</div>
</div>
</SkillProvider>
);
}
export default Skill;
SkillsList
import Skill from "../components/Skill";
import styles from "../../styles/Home.module.scss";
import ReactPlaceholder from "react-placeholder";
import useRequestDelay, { REQUEST_STATUS} from "../hooks/useRequestDelay";
import { data } from '../../SkillData';
import { CourseFilterContext} from "../contexts/CourseFilterContext";
import { useContext } from "react";
function SkillsList () {
const {
data: skillData,
requestStatus,
error,
updateRecord,
insertRecord,
deleteRecord
} = useRequestDelay(2000, data)
const { searchQuery, courseYear } = useContext(CourseFilterContext);
if(requestStatus === REQUEST_STATUS.FAILURE) {
return(
<div className="text-danger">
Error: <b>Loading Speaker Data Failed {error}</b>
</div>
)
}
//if (isLoading === true) return <div className="mb-3">Loading...</div>
return (
<div className={styles.container, "container"}>
<ReactPlaceholder
type="media"
rows={15}
className="skillsList-placeholder"
ready={requestStatus === REQUEST_STATUS.SUCCESS}
>
<div className="row">
{skillData
.filter(function (skillCard) {
return (
skillCard.skill.toLowerCase().includes(searchQuery)
);
})
.filter(function (skillCard) {
return skillCard.courses.find((course) => {
return course.year === courseYear;
})
})
.map(function (skillCard) {
return (
<Skill
key={skillCard.id}
skillCard={skillCard}
updateRecord={updateRecord}
insertRecord={insertRecord}
deleteRecord={deleteRecord}
/>
);
})}
</div>
</ReactPlaceholder>
</div>
);
}
export default SkillsList;
SkillContext
import { createContext } from "react";
const SkillContext = createContext();
function SkillProvider({children, skillCard, updateRecord, insertRecord, deleteRecord}) {
return (
<SkillContext.Provider
value={skillCard, updateRecord, insertRecord, deleteRecord}>
{children}
</SkillContext.Provider>
)
}
export { SkillContext, SkillProvider}

How can i make a counter for each component in functional component?

Halo everybody, i want to ask for my problem right now..
i want to make a counter in each component list.. i already have a function for handle the counter, but the counter doesnt increment in spesific id. that function increment the counter value for all component.. please help me
there is my code
MenuPage.js
import React, { useEffect, useState } from "react";
import "../../assets/index.css";
import ProductList from "../../components/ProductList";
import { productList } from "../../components/constant/productList";
import NavigationBottom from "../../components/NavigationBottom";
function MenuPage() {
const [showDisplay, setShowDisplay] = useState("grid");
const [quantityProduct, setQuantityProduct] = useState(0);
const handleShowDisplay = (e) => {
setShowDisplay(e);
};
const handleAdd = (value, idx) => {
if (value.id === idx + 1) {
setQuantityProduct(quantityProduct + 1);
} else {
setQuantityProduct(0);
}
};
const handleMinus = () => {
if (quantityProduct === 0) {
return 0;
}
setQuantityProduct(quantityProduct - 1);
};
return (
<div className="main_container">
<div className="container_menu__style">
<div
onClick={() => handleShowDisplay("grid")}
className="button_grid__view"
>
<i class="bi bi-grid"></i>
</div>
<div
onClick={() => handleShowDisplay("list")}
className="button_list__view"
>
<i class="bi bi-list"></i>
</div>
</div>
<div
className={` ${
showDisplay === "grid"
? "container_menu__page"
: "container_menu__page_list"
}`}
>
{productList.map((item, idx) => {
return (
<ProductList
key={idx}
id={idx}
item={item}
quantityProduct={quantityProduct}
showDisplay={showDisplay}
handleAdd={handleAdd}
handleMinus={handleMinus}
/>
);
})}
<NavigationBottom />
</div>
</div>
);
}
export default MenuPage;
ProductList.js
import React from "react";
function ProductList({
id,
item,
quantityProduct,
showDisplay,
handleAdd,
handleMinus,
}) {
return (
<div
className={` ${
showDisplay === "grid"
? "wrapper_menu__product"
: "wrapper_menu__product_list"
}`}
>
<div
className={` ${
showDisplay === "grid"
? "content_menu__product"
: "content_menu__product_list"
}`}
>
<div
className={`${
showDisplay === "grid"
? "image_menu__product"
: "image_menu__product_list"
}`}
>
<img
alt="product-list"
className={` ${showDisplay === "grid" ? "" : "img_list"}`}
src="https://i.pinimg.com/originals/23/91/52/2391523603cbd5153d7eb4e37eb3c882.png"
/>
</div>
<div className="wrapper_menu__detail">
<div className="container_menu">
<div className="menu_title__product">{item.product_name}</div>
<div className="menu_price__product">Rp. {item.product_price}</div>
</div>
<div className="container_quantity">
{/* <div className="quantity_text">Jumlah pesanan</div> */}
<button
className="button_minus__product"
onClick={() => handleMinus(item)}
>
<i class="bi bi-dash"></i>
</button>
<div className="quantity_product">{quantityProduct}</div>
<button
className="button_add__product"
onClick={() => handleAdd(item, id)}
>
<i class="bi bi-plus"></i>
</button>
</div>
{/* <div className="wrapper_quantity__product">
<div className="quantity_product__text">Jumlah Pesanan</div>
<div className="quantity_product__number"></div>
</div> */}
</div>
</div>
</div>
);
}
export default ProductList;
Your MenuPage only has a single quantityProduct (and setQuantityProduct) variable. All items are using and setting this same variable.

Resources