Changing the css style of element depending on its content. Angular - javascript

I am making product cards for an online store and I need the color of each card to change depending on the size of the discount on the product. For example: if the discount is more than 50%, then the card is red, if less - orange. Product data is stored in a variable in the component code, so I use *ngFor to display this data. I thought to do it using [ngClass], but there the variable can only be checked for true or False, the custom condition will not be set. How else can it be done?
component.html
<div class="products-list">
<div id="{{item.id}}" class="item" *ngFor="let item of items">
<div class="item__container">
<div class="item__content">
<div class="item__off" *ngIf="item.offer">
<p>{{item.offer}}%</p>
<p>off</p>
</div>
<div class="item__desc">
{{item.description}}
</div>
<div class="item__price-offer price" *ngIf="item.offer">
<div class="item__off-price">
${{item.offPrice}}
</div>
<div class="item__real-price">
${{item.realPrice}}
</div>
</div>
<div class="item__price price" *ngIf="!item.offer">
${{item.realPrice}}
</div>
</div>
<div class="item__image">
<img src="../../assets/img/{{item.image}}" alt="Error!">
</div>
</div>
<div class="item__addition">
<div class="addition" *ngFor="let addition of item.addition">
{{addition}}
</div>
</div>
</div>
</div>
component.ts
{offer: 60, description: "Stand mixer with extra power handle ppreciation Gift backet", offPrice: 49.99, realPrice: 69.99, image: "mixer.png", addition: ["Free Shipping", "New"]},
{offer: 20, description: "Stand mixer with extra power handle ppreciation Gift backet", offPrice: 49.99, realPrice: 69.99, image: "mixer.png", addition: ["Free Shipping", "New"]},
{offer: 60, description: "Stand mixer with extra power handle ppreciation Gift backet", offPrice: 49.99, realPrice: 69.99, image: "mixer.png", addition: ["New"]},
{offer: 10, description: "Stand mixer with extra power handle ppreciation Gift backet", offPrice: 49.99, realPrice: 69.99, image: "mixer.png", addition: ["Free Shipping"]},
{offer: 60, description: "Stand mixer with extra power handle ppreciation Gift backet", offPrice: 49.99, realPrice: 69.99, image: "mixer.png", addition: ["Free Shipping"]},
{description: "Stand mixer with extra power handle ppreciation Gift backet", offPrice: 49.99, realPrice: 69.99, image: "mixer.png", addition: ["New"]},
{offer: 60, description: "Stand mixer with extra power handle ppreciation Gift backet", offPrice: 49.99, realPrice: 69.99, image: "mixer.png", addition: ["Free Shipping"]},
{offer: 60, description: "Stand mixer with extra power handle ppreciation Gift backet", offPrice: 49.99, realPrice: 69.99, image: "mixer.png", addition: ["Free Shipping", "New"]},
];
}

Related

How do i use the next image components

I uploaded images on image kit , so i can use the image link in my project. I kep getting errors i dont know why . I followed the documentation thoroughly .
Here is my next config file
module.exports = {
images: {
domain: ['ik.imagekit.io'],
},
}
Here is a javascript file that i used to store the images , swhich is then mapped to another file
const vondutch = [
{
id: '0',
name: 'Von dutch pink',
category: 'Shirts',
image: "https://ik.imagekit.io/juwoncaleb/l5_ZBzjfMqVE.jpg?ik-sdk-version=javascript-1.4.3&updatedAt=1643717156193",
image: "https://ik.imagekit.io/juwoncaleb/l5_ZBzjfMqVE.jpg?ik-sdk-version=javascript-1.4.3&updatedAt=1643717156193",
image: "https://ik.imagekit.io/juwoncaleb/l5_ZBzjfMqVE.jpg?ik-sdk-version=javascript-1.4.3&updatedAt=1643717156193",
image: "https://ik.imagekit.io/juwoncaleb/l5_ZBzjfMqVE.jpg?ik-sdk-version=javascript-1.4.3&updatedAt=1643717156193",
image: "https://ik.imagekit.io/juwoncaleb/l5_ZBzjfMqVE.jpg?ik-sdk-version=javascript-1.4.3&updatedAt=1643717156193",
price: 30000,
rating: 4.5,
size: 10,
},
{
id: '1',
name: 'Von dutch blue',
category: 'Shirts',
image: "https://ik.imagekit.io/juwoncaleb/l5_ZBzjfMqVE.jpg?ik-sdk-version=javascript-1.4.3&updatedAt=1643717156193",
image: "https://ik.imagekit.io/juwoncaleb/l5_ZBzjfMqVE.jpg?ik-sdk-version=javascript-1.4.3&updatedAt=1643717156193",
image: "https://ik.imagekit.io/juwoncaleb/l5_ZBzjfMqVE.jpg?ik-sdk-version=javascript-1.4.3&updatedAt=1643717156193",
image: "https://ik.imagekit.io/juwoncaleb/l5_ZBzjfMqVE.jpg?ik-sdk-version=javascript-1.4.3&updatedAt=1643717156193",
image: "https://ik.imagekit.io/juwoncaleb/l5_ZBzjfMqVE.jpg?ik-sdk-version=javascript-1.4.3&updatedAt=1643717156193",
image: "https://ik.imagekit.io/juwoncaleb/l5_ZBzjfMqVE.jpg?ik-sdk-version=javascript-1.4.3&updatedAt=1643717156193",
price: 15000,
brand: 'Adidas',
rating: 4.0,
size: 10,
}
]
export default vondutch;
Here is where the image from the file above is used in a next file
<div class="slides">
<Image
id="slide-1"
class="imagesli"
src={image}
/>
<div>
<Image src={image1} />
</div>
<div id="slide-2">
<Image src={image2} />
</div>
<div id="slide-3">
<Image src={image3} />
</div>
<div id="slide-4">
<Image src={image4} />
</div>
<div id="slide-5">
<Image src={image5} />
</div>
</div>
you may want to map your elements
get array of all URLS-s of images you want to set
var images = [url_1, url_2, url_3...]
and then you should just
<div class="slides">
<Image
id="slide-1"
class="imagesli"
src={image}
/>
{images.map((url, index) => (
<div key={index} id={`slide-${index+1}`} >
<Image src={url} />
</div>
))}
</div>

React: hide and show specific elements from array displayed using map()

The goal is to display a series of recipes. The user first gets a general overview of the available recipes containing the name of the recipe, a picture, and some basic information (time to cook, etc). When the user clicks a button (show full recipe), the full recipe should be shown. When the user clicks a new button (hide full recipe) the full recipe is hidden again and the user only sees a general overview of the recipes.
For now, I have created an array of (two) recipes. By using a map() I return the different recipes. However, when the show or hide full recipe button is clicked, all the recipes are shown. How can I make sure that when the user clicks 'show full recipe', he/she only gets to see the specific recipe?
import React, { useState } from 'react';
var recipes = [{
_id: 1,
title: "Spaghetti",
type: "Dinner or Lunch",
category: "vegan",
image: "http://via.placeholder.com/350x250",
cookingTime: 35,
ingredients: [[1, "onion"], [3, "tomato"], [1, "aubergine"], [1, "beans"], [1, "tomatoesauce"], [1, "tomatoconcentrate"], [1, "pepper"], [1, "salt"], [1, "pasta"]],
cookingSteps: [["Boil a pot full of watter. Once the watter is boiling, add the pasta. The cooking time depends on the pasta."], ["Cut the onion and the garlic. Add them to a poth with olive oil. Cook for 2 to 3 minutes"], ["Cut the other vegetables. After the onion and the garlic are marrinated, add the different vegtables to the poth. Let them cook with the lid on for about 10 to 15 minutes or untill the vegetables are ready."], ["Once the vegetables are ready, add the tomato sauce and the tomato concentrate. Add the beans. Let this cook for another five minutes"], ["Remove the lid from the pot. Add pepper and salt and other additional spcices, like italian spcies or special peppers"]]
},
{
_id: 2,
title: "Eggs",
type: "Breakfast",
category: "vegan",
image: "http://via.placeholder.com/350x250",
cookingTime: 10,
ingredients: [[4, "egg"], [1, "tomato"], [1, "pepper"], [1, "salt"]],
cookingSteps: [["cut the tomato. Heat olive oil in a pan, add the tomato and bake it till the outer peal of the tomato gets soft. If you like pepper, it is adviced to first bake the pepper a bit in the pan"], ["Meanwhile, scrambel the eggs. Once the tomatoes are ready (see step 1), add the eggs"]]
}
];
//TODO: make sure only one specific recipe shows when clicked
function DisplayRecipes(){
//declare useState and onClick for button to show full recipe
const[isNotDisplayed, isDisplayed] = React.useState(false)
const onClickShow = () => {isDisplayed(true)};
const onClickHIde = () => isDisplayed(false);
//return statement to render recipe
return(
<div className="card-list">
<div className="container">
<h1 className="page-title">Our vegan recipes...</h1>
<div className="row">
{
recipes.map((recipe)=>{
return(
<div key={recipe._id} className="col-md-3">
<div className="card bwm-card">
<div className="card-title">
<h2>{recipe.title}</h2>
</div>
<img className="card-img-top" src={recipe.image} alt={recipe.title} />
<div className="card-subtitle">
<h3><b>Type: {recipe.type} </b></h3>
<h3><b>Category: {recipe.category}</b></h3>
<h3><b>Cooking time: {recipe.cookingTime} minutes</b></h3>
</div>
<div>
{ isNotDisplayed ?
<div className="card-body">
<div className="card-body-ingredient">
{
recipe.ingredients.map((ingredient, i) =>{
return(
<table>
<tr>
<th>Quantity</th>
<th>Ingredient</th>
</tr>
<tr>
<th>{ingredient[0]}</th>
<th>{ingredient[1]}</th>
</tr>
</table>
)
})
}
</div>
<div className="card-body-cookingsteps">
{
recipe.cookingSteps.map((cookingstep, i) =>{
return(
<p>{cookingstep}</p>
)
})
}
</div>
<div>
<button type="submit" value="Hide full recipe" onClick= {onClickHIde}>Hide full recipe</button>
</div>
</div>
:
<button type="submit" value="Show full recipe" onClick= {onClickShow}>Show full recipe</button>
}
</div>
</div>
</div>
)
})
}
</div>
</div>
</div>
)
}
export default DisplayRecipes;
Thank you in advance!
You need a separate piece of state for each recipe. Currently all the recipes share the same state, so when one is open, they're all open.
The best way to separate out the state is to make each recipe its own component with its own state.
import React, {useState} from 'react';
const recipes = [
{
_id: 1,
title: 'Spaghetti',
type: 'Dinner or Lunch',
category: 'vegan',
image: 'http://via.placeholder.com/350x250',
cookingTime: 35,
ingredients: [
[1, 'onion'],
[3, 'tomato'],
[1, 'aubergine'],
[1, 'beans'],
[1, 'tomatoesauce'],
[1, 'tomatoconcentrate'],
[1, 'pepper'],
[1, 'salt'],
[1, 'pasta'],
],
cookingSteps: [
[
'Boil a pot full of watter. Once the watter is boiling, add the pasta. The cooking time depends on the pasta.',
],
[
'Cut the onion and the garlic. Add them to a poth with olive oil. Cook for 2 to 3 minutes',
],
[
'Cut the other vegetables. After the onion and the garlic are marrinated, add the different vegtables to the poth. Let them cook with the lid on for about 10 to 15 minutes or untill the vegetables are ready.',
],
[
'Once the vegetables are ready, add the tomato sauce and the tomato concentrate. Add the beans. Let this cook for another five minutes',
],
[
'Remove the lid from the pot. Add pepper and salt and other additional spcices, like italian spcies or special peppers',
],
],
},
{
_id: 2,
title: 'Eggs',
type: 'Breakfast',
category: 'vegan',
image: 'http://via.placeholder.com/350x250',
cookingTime: 10,
ingredients: [
[4, 'egg'],
[1, 'tomato'],
[1, 'pepper'],
[1, 'salt'],
],
cookingSteps: [
[
'cut the tomato. Heat olive oil in a pan, add the tomato and bake it till the outer peal of the tomato gets soft. If you like pepper, it is adviced to first bake the pepper a bit in the pan',
],
[
'Meanwhile, scrambel the eggs. Once the tomatoes are ready (see step 1), add the eggs',
],
],
},
];
const Recipe = ({recipe}) => {
const [isOpen, setIsOpen] = React.useState(false);
return (
<div className="col-md-3">
<div className="card bwm-card">
<div className="card-title">
<h2>{recipe.title}</h2>
</div>
<img className="card-img-top" src={recipe.image} alt={recipe.title} />
<div className="card-subtitle">
<h3>
<b>Type: {recipe.type} </b>
</h3>
<h3>
<b>Category: {recipe.category}</b>
</h3>
<h3>
<b>Cooking time: {recipe.cookingTime} minutes</b>
</h3>
</div>
<div>
{isOpen ? (
<div className="card-body">
<div className="card-body-ingredient">
{recipe.ingredients.map((ingredient, i) => {
return (
<table>
<tr>
<th>Quantity</th>
<th>Ingredient</th>
</tr>
<tr>
<th>{ingredient[0]}</th>
<th>{ingredient[1]}</th>
</tr>
</table>
);
})}
</div>
<div className="card-body-cookingsteps">
{recipe.cookingSteps.map((cookingstep, i) => {
return <p>{cookingstep}</p>;
})}
</div>
<div>
<button
type="submit"
value="Hide full recipe"
onClick={() => setIsOpen(false)}>
Hide full recipe
</button>
</div>
</div>
) : (
<button
type="submit"
value="Show full recipe"
onClick={() => setIsOpen(true)}>
Show full recipe
</button>
)}
</div>
</div>
</div>
);
};
function DisplayRecipes() {
return (
<div className="card-list">
<div className="container">
<h1 className="page-title">Our vegan recipes...</h1>
<div className="row">
{recipes.map((recipe) => (
<Recipe key={recipe._id} recipe={recipe} />
))}
</div>
</div>
</div>
);
}
export default DisplayRecipes;
You can consider using refs here:
Pass the ref to your onClickShow and show the div with that particular ref.
You can also use CSS, in this case, get the div using the ref and mark display of that div as none and vice-versa.

How to manipulate OnClick method on my React App?

I'm trying to create a basic react app which contains 4 Reactstrap Card Items and now I want this functionality where when I click at one of the cards, the clicked card gets copied all the way at the end of the page and we display additional information related to the card.
Here is one of the component code-
import React,{useState} from "react";
import 'bootstrap/dist/css/bootstrap.min.css';
import {Card, CardImg, CardImgOverlay, CardText, CardBody,
CardTitle} from "reactstrap";
function MenuComponent (props){
return (
<div className="container">
<div className="row">
{props.dishes.map((dish)=>{
return (
<div className="col-12 col-md-5 m-1">
<Card key={dish.id} >
<CardImg width="100%" src={dish.image} alt={dish.name} />
<CardImgOverlay>
<CardTitle>{dish.name}</CardTitle>
</CardImgOverlay>
</Card>
</div>
);
}
)
}
</div>
</div>
);
}
export default MenuComponent;
Here is the Dishes array of objects having the details about the dish-
Dishes=[
{
id: 0,
name:'Uthappizza',
image: 'asset/images/uthappizza.png',
category: 'mains',
label:'Hot',
price:'4.99',
description:'A unique combination of Indian Uthappam (pancake) and Italian pizza, topped with Cerignola olives, ripe vine cherry tomatoes, Vidalia onion, Guntur chillies and Buffalo Paneer.' },
{
id: 1,
name:'Zucchipakoda',
image: 'asset/images/zucchipakoda.png',
category: 'appetizer',
label:'',
price:'1.99',
description:'Deep fried Zucchini coated with mildly spiced Chickpea flour batter accompanied with a sweet-tangy tamarind sauce' },
{
id: 2,
name:'Vadonut',
image: 'asset/images/vadonut.png',
category: 'appetizer',
label:'New',
price:'1.99',
description:'A quintessential ConFusion experience, is it a vada or is it a donut?' },
{
id: 3,
name:'ElaiCheese Cake',
image: 'asset/images/elaicheesecake.png',
category: 'dessert',
label:'',
price:'2.99',
description:'A delectable, semi-sweet New York Style Cheese Cake, with Graham cracker crust and spiced with Indian cardamoms' }
];
If you need to copy the content of a dish, it's possible to use this lib https://www.npmjs.com/package/copy-to-clipboard in this way.
import React, { useState } from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import {
Card,
CardImg,
CardImgOverlay,
CardText,
CardBody,
CardTitle,
} from "reactstrap";
import copy from "copy-to-clipboard";
function MenuComponent(props) {
const copyHandler = (dish) => {
copy(dish.name);
};
return (
<div className="container">
<div className="row">
{props.dishes.map((dish) => {
return (
<div className="col-12 col-md-5 m-1">
<Card key={dish.id} onClick={() => copyHandler(dish)}>
<CardImg width="100%" src={dish.image} alt={dish.name} />
<CardImgOverlay>
<CardTitle>{dish.name}</CardTitle>
</CardImgOverlay>
</Card>
</div>
);
})}
</div>
</div>
);
}
export default MenuComponent;
But if you need to get a new copy of the element, the best choice would be to receive the setState function for props and execute in a handler like in the example above or apply the dishes in the component's state.

How to implement pagination over cards using table method pagination

i'm using table pagination template to make a pagination over cards. the pagination seems working but data isn't loaded.
This is my html component : If i change my datasource2 inside ngFor, the data is loaded but with no pagination rules.
<mat-card *ngFor="let item of dataSource2" >
<!--cart header-->
<mat-card-header>
<div mat-card-avatar class="example-header-image"></div>
<mat-card-title > <a href="" > {{item.title}} </a> </mat-card-title>
<mat-card-subtitle > {{item.subtitle}} </mat-card-subtitle>
</mat-card-header>
<img mat-card-image src="{{ item.imgsrc }}" alt="Photo of a Shiba Inu" >
<mat-card-content> <p> {{item.content}} </p> </mat-card-content>
<mat-card-actions>
<button mat-button>LIKE</button>
<button mat-button>SHARE</button>
</mat-card-actions>
</mat-card>
<mat-paginator [pageSizeOptions]="[5, 10, 20]" showFirstLastButtons></mat-paginator>
</div>
the component ts :
export class CardsComponent implements AfterViewInit {
displayedColumns: string[] = ['position', 'title', 'subtitle', 'content','imgsrc'];
dataSource2 = new MatTableDataSource<PeriodicElement>(ELEMENT_DATA);
#ViewChild(MatPaginator) paginator: MatPaginator;
ngAfterViewInit() {
this.dataSource2.paginator = this.paginator;
}
}
const ELEMENT_DATA: PeriodicElement[] = [
{position: 1, title: 'Shiba Inu Yes', subtitle:'Dog Breed',content:'The Shiba Inu is the smallest' , imgsrc:'https://material.angular.io/assets/img/examples/shiba2.jpg'},
{position: 2, title: 'Shiba Inu', subtitle:'Dog Breed',content:'The Shiba Inu is the smallest' , imgsrc:'https://material.angular.io/assets/img/examples/shiba2.jpg'},
{position: 3, title: 'Shiba Inu', subtitle:'Dog Breed',content:'The Shiba Inu is the smallest' , imgsrc:'https://material.angular.io/assets/img/examples/shiba2.jpg'},
{position: 4, title: 'Shiba Inu', subtitle:'Dog Breed',content:'The Shiba Inu is the smallest' , imgsrc:'https://material.angular.io/assets/img/examples/shiba2.jpg'},
{position: 5, title: 'Shiba Inu', subtitle:'Dog Breed',content:'The Shiba Inu is the smallest' , imgsrc:'https://material.angular.io/assets/img/examples/shiba2.jpg'},
{position: 6, title: 'Shiba Inu', subtitle:'Dog Breed',content:'The Shiba Inu is the smallest' , imgsrc:'https://material.angular.io/assets/img/examples/shiba2.jpg'},
{position: 7, title: 'Shiba Inu', subtitle:'Dog Breed',content:'The Shiba Inu is the smallest' , imgsrc:'https://material.angular.io/assets/img/examples/shiba2.jpg'},
];
export interface PeriodicElement {
position: number;
title: string;
subtitle: string;
content: string;
imgsrc: string;
}

How can I prevent a re-render error in my functional component?

I am new to using React Hooks with stateless components. I usually use stateful components when I have to use state. My present app requires the context API which could only be used in functional Components. I have rewritten most of the code I need to work but one brings an error "Error: Too many re-renders. React limits the number of renders to prevent an infinite loop."
The Component I am trying to convert to a functional one
class pizzas extends Component {
state ={
pizzas: [
{id:1, name: 'Chicken Curry', ingredients: 'Red onions, bell peppers, chicken, pineapple, mozzarella, tomato sauce, curry, chili peppers', price: '3100', image: chickenCurry },
{id:2, name: 'Pepperoni Fresh', ingredients: 'Pepperoni, mozzarella, green peppers, pizza sauce', price: '2700', image: pepperoniFresh },
{id:3, name: 'Chicken BBQ', ingredients: 'Chicken, red onions, corn, mozzarella, bbq sauce, tomato sauce', price: '2700', image: chickenBbq },
{id:4, name: 'Shawarma Pizza', ingredients: 'Mayonnaise & ketchup, spicy chicken, red onions, tomatoes, mozzarella', price: '3100', image: sharwarmaPizza },
{id:5, name: 'Chicken Suya', ingredients: 'Mayonnaise, spicy sauce, spicy chicken, bell peppers, red onions, suya sauce, tomato sauce, mozzarella, suya spice', price: '2700', image: chickenSuya },
{id:6, name: 'Pepperoni', ingredients: 'Pepperoni, mozzarella, tomato sauce', price: '2700', image: pepperoni },
{id:7, name: 'Beef Suya', ingredients: 'Mayonnaise, spicy sauce, spicy meatballs, bell peppers, red onions, mozzarella, suya sauce, tomato sauce, suya spice', price: '2700', image: beefSuya },
{id:8, name: 'Chicken Supreme', ingredients: 'Spicy sauce, chicken and spicy chicken, mushrooms, bell peppers, olives, red onions, mozzarella, tomato sauce', price: '3100', image: chickenSupreme },
{id:9, name: 'Sweet Chili Chicken', ingredients: 'Spicy sauce, chicken, chili pepper, mozzarella, sweet chili sauce, tomato sauce', price: '2700', image: chickenCurry },
{id:10, name: 'Spicy Mixed Pizza', ingredients: 'Spicy sauce, spicy meatballs, spicy chicken, chili pepper, corn, mozzarella, buffalo sauce, tomato sauce', price: '3100', image: spicyMixedPizza },
{id:11, name: 'Margherita', ingredients: 'Mozarella, tomato sauce', price: '2200', image: margherita },
{id:12, name: 'Super Meaty', ingredients: 'Chicken, pepperonni, sausages, mozzarella, tomato sauce', price: '3100', image: superMeaty },
{id:13, name: 'Cheesy Chicken', ingredients: 'Chicken, tomatoes, cheddar, mozzarella, cheese sauce', price: '2700', image: cheesyChicken },
{id:14, name: 'Cheeseburger Pizza', ingredients: 'Beef, tomatoes, red onions, cheddar, mozzarella, mayonnaise & ketchup, tomato sauce', price: '3100', image: cheeseBurger },
{id:15, name: 'Meaty Overload', ingredients: 'Spicy sauce, pepperonni, spicy meatballs, chicken, sausages, mozzarella, tomato sauce', price: '3400', image: meatyOverload },
{id:16, name: 'Meaty BBQ', ingredients: 'Beef, pepperonni, sausages, mozzarella, bbq sauce, tomato sauce', price: '3100', image: meatyBbq },
{id:17, name: 'Hawaiian', ingredients: 'Chicken, pineapple, mozzarella, sweet chili sauce, tomato sauce', price: '2700', image: hawaiian },
{id:18, name: 'Veggie Overload', ingredients: 'Mushrooms, bell peppers, corn, olives, red onions, tomatoes, mozzarella, tomato sauce', price: '3100', image: veggieOverload }
],
showModal: false,
selectedPizza: null,
orders: []
}
toggleModalHandler = (p)=>{
this.setState({showModal: !this.state.showModal, selectedPizza: p});
}
addToOrders = (productName, productIngredients, productPrice, productImage, p)=>{
this.setState(prevState=>({
orders: [...prevState.orders, productImage, productName, productIngredients, productPrice]
}))
}
render(){
const pizza = this.state.pizzas;
return (
<Aux>
{ this.state.showModal?
<Backdrop clicked={this.toggleModalHandler}/>: null}
{ this.state.showModal ?
<Modal
clicked={this.toggleModalHandler}
sendRequest={this.sendingRequestHandler}
ingredients={this.state.selectedPizza.ingredients}
price={this.state.selectedPizza.price}
image={this.state.selectedPizza.image}
name={this.state.selectedPizza.name}
key={this.state.pizzas.id}
addToOrders={this.addToOrders}/>: null}
<div className={styles.Pizza} id="pizza">
<h1>Pizza</h1>
<div className={styles.PizzaContainer}>
{pizza.map(p=>{
return <div>
<div className={styles.PizzaCard}>
<div className={styles.PizzaCardHeader}>
<img src={p.image} alt="pizza"/>
<h1>{p.name}</h1>
<p>{p.ingredients}</p>
</div>
<div className={styles.PizzaCardFooter}>
<h3>from ₦{p.price}</h3>
<button onClick={()=>this.toggleModalHandler(p)}>Select</button>
</div>
</div>
</div>
})}
</div>
</div>
</Aux>
)
}
}
export default pizzas;
What I have done so far
const Pizzas = () => {
const [showModal, setModal] = useState(false);
const [selectedPizza, setSelectedPizza] = useState(null)
const { pizzaproducts } = useContext(ProductsContext)
const toggleModalHandler = (p) => {
setModal(true);
setSelectedPizza(p)
}
return (
<Aux>
{setModal(true) ?
<Backdrop clicked={toggleModalHandler} /> : null}
{setModal(true) ?
<Modal
clicked={toggleModalHandler}
ingredients={selectedPizza.ingredients}
price={selectedPizza.price}
image={selectedPizza.image}
name={selectedPizza.name}
/> : null}
<div className={styles.Pizza} id="pizza">
<h1>Pizza</h1>
<div className={styles.PizzaContainer}>
{pizzaproducts.map(p => {
return <div>
<div className={styles.PizzaCard}>
<div className={styles.PizzaCardHeader}>
<img src={p.image} alt="pizza" />
<h1>{p.name}</h1>
<p>{p.ingredients}</p>
</div>
<div className={styles.PizzaCardFooter}>
<h3>from ₦{p.price}</h3>
<button onClick={() => toggleModalHandler(p)}>Select</button>
</div>
</div>
</div>
})}
</div>
</div>
</Aux>
)
}
export default Pizzas;
How best can I convert this? I am guessing this error is from the togglemodalhandler. I am new to hooks.
You shouldn't set state inside the template. This triggers re-render, what again, trigger setting state and next...
Try something like this:
import React, { useState, useContext } from 'react';
const Pizzas = () => {
const [showModal, setModal] = useState(false);
const [selectedPizza, setSelectedPizza] = useState(null)
const { pizzaproducts } = useContext(ProductsContext)
const toggleModalHandler = (p) => {
setModal(true);
setSelectedPizza(p)
};
return (
<Aux>
{showModal ? <Backdrop clicked={toggleModalHandler} /> : null}
{showModal ?
<Modal
clicked={toggleModalHandler}
ingredients={selectedPizza.ingredients}
price={selectedPizza.price}
image={selectedPizza.image}
name={selectedPizza.name}
/> : null}
<div className={styles.Pizza} id="pizza">
<h1>Pizza</h1>
<div className={styles.PizzaContainer}>
{pizzaproducts.map(p => {
return <div>
<div className={styles.PizzaCard}>
<div className={styles.PizzaCardHeader}>
<img src={p.image} alt="pizza" />
<h1>{p.name}</h1>
<p>{p.ingredients}</p>
</div>
<div className={styles.PizzaCardFooter}>
<h3>from ₦{p.price}</h3>
<button onClick={() => toggleModalHandler(p)}>Select</button>
</div>
</div>
</div>
})}
</div>
</div>
</Aux>
)
}
export default Pizzas;
You are conditionally attempting to render using setModal(true)?, which is incorrect, should be showModal?
useState returns a pair of values: the current state and a function that updates it. This is why we write const [showModal, setModal] = useState(). This is similar to this.state.showModal and this.setState in a class, except you get them in a pair.

Categories

Resources