I'm having trouble making a button in each product that pops an alert and tells about the item's description. I can get the button to appear in each product but it's making the event that's giving me trouble.
Here's my code:
Product.js:
import React from "react"
function Products(props){
return(
<div className="list">
<h3>{props.product.name}</h3>
<p style={{color: props.product.price >= 10 ? "red" : "yellow"}}>Price: ${props.product.price}</p>
<p>{props.product.description}</p>
<hr/>
</div>
)
}
export default Products
App.js:
import React from 'react'
import productsData from "./vschoolProducts"
import Products from "./Products"
function App(){
const productsComponent = productsData.map(item => <Products key={item.id} product={item} />);
return (
<div>
{productsComponent}
</div>
);
}
export default App
My Array (vschoolProducts.js):
const products = [
{
id:"1",
name:"Pencil",
price:1,
description:"Something you write with. "
},
{
id:"2",
name:"Pen",
price:3,
description:"Something you write with....permanently "
},
{
id:"3",
name:"Paper",
price:7,
description:"Something you write on. "
},
{
id:"4",
name:"Binder",
price:4,
description:"Useful for sorting shit. "
},
{
id:"5",
name:"Notebook",
price:10,
description:"Great for jotting notes down. "
},
{
id:"6",
name:"Backpack",
price:12,
description:"Can hold all the previous products. "
}
]
export default products
CodePudding user response:
If I'm right in thinking that you want every product to alert it's description when clicked then I believe you can do this. Add an onclick event to your product component.
const productsComponent = productsData.map(item => <Products key={item.id} product={item} onClick={() => {alert(item.description);}} />);
CodePudding user response:
Essentially if I was doing something like this in my app. This is the way I would do it: Create two states, one for toggling my alert's visibility, another for holding my alert message. Then I would generate my products like this
<>
<div className="list">
<h3>{props.product.name}</h3>
<p style={{color: props.product.price >= 10 ? "red" : "yellow"}}>Price: ${props.product.price}</p>
<p>{props.product.description}</p>
<hr/>
<Button
variant="outlined"
onClick={() => {
setAlertMessage(product.description);
showMyAlertComponent(true);
setTimeout(() =>
showMyAlertComponent(false)
,6000);
}}
>
Click Me
</Button>
What is happening above is I am creating a button for all my products and creating an onclick listener that does the following: Sets my alert message, shows my alert and then hides it after 6 seconds. If you are using an alert component like Material -UI component, you could use autoHideDuration instead of writing the setTimeout code.
Then I just return my generated products and my alert component. I will pass the value of my alert message state to my alert component, so it changes whenever the user clicks on a different item.
<>
{generationFunction}
<Alert
autoHideDuration={6000}
>
{alertMessage}
</Alert>
</>
So in this way, I would need only 1 Alert component for all my items. If you are just using browser's alert function though it's even simpler.
const generationFunction = products.map((product) => {
return(
<>
<div className="list">
<h3>{props.product.name}</h3>
<p style={{color: props.product.price >= 10 ? "red" : "yellow"}}>Price: ${props.product.price}</p>
<p>{props.product.description}</p>
<hr/>
<Button
variant="outlined"
onClick={() => {
alert(product.description)
}}
>
Click Me
</Button>
</div>
</>
);
});
return(generationFunction);
Full code
import { useState } from "react";
import { Button, Alert } from "@mui/material";
const products = [
{
id:"1",
name:"Pencil",
price:1,
description:"Something you write with. "
},
{
id:"2",
name:"Pen",
price:3,
description:"Something you write with....permanently "
},
];
const GenerateProducts = () => {
// create a state for my alert message
const [alertMessage, setAlertMessage] = useState("");
//create a state to toggle ur alert component, set State to false initially
const [showMyAlertComponent, setShowMyAlertComponent] = useState(false);
//generating components using your products array
const generationFunction = products.map((product) => {
// Generate buttons Whatever other component you want to generate
//define onClick handler that sets your alertMessage and then shows it
return(
<>
<div className="list">
<h3>{props.product.name}</h3>
<p style={{color: props.product.price >= 10 ? "red" : "yellow"}}>Price: ${props.product.price}</p>
<p>{props.product.description}</p>
<hr/>
<Button
variant="outlined"
onClick={() => {
setAlertMessage(product.description);
showMyAlertComponent(true);
setTimeout(() =>
showMyAlertComponent(false)
,6000);
}}
>
Click Me
</Button>
</div>
</>
);
});
return(
<>
{generationFunction}
<Alert>
{alertMessage}
</Alert>
</>
);
}