I have a component called "itemSelection" and another one called "Item"
in the itemSelection i just map through an api response like this
<div className="row">
{this.state.items.map(i => <Item name={i.name} quantity={i.quantity} />)}
</div>
in the "Item" component I have like 3 card item with a select button. in its state there is also "quantity" key but that's for the quantity selected by the user of a specific item. So, what I'm try to achieve here is if the user selected one item and quantity of 2, I want to take that in an object and put that object in an array, and if the user selected another item with quantity of 3, I want that in another object and just push that object in the array where I have put the first object to be something like that
[{name: first item, quantity: 2}, {name: second item, quantity: 3}]
here is what I tried
targetValue = (e) => {
e.preventDefault();
let qua = e.target.textContent;
this.setState({quantity: qua, selected: true});
const newQuantity = {name: this.props.name, quantity: qua}
const quantities = [...this.state.quantities];
quantities.push(newQuantity);
this.setState({quantities});
console.log(quantities);
}
The function above is included in the "Item.js" and here is the return function
<div className="col-md-4">
<div className={"card " + (this.state.selected ? "frame" : "")} style={{width: 18+'rem'}}>
<img className="card-img-top" style={{width: 10+'rem', margin: 0+' '+'auto'}} src={this.props.img} alt="Card image cap"/>
<div className="card-body">
<h5 className="card-title">{this.props.name}</h5>
<p clasNames="card-text">Lorem ipsum dolor sit amet, consectetur adipisicing elit</p>
<div className="description">
<p className="card-text">30€</p>
<p className={"card-text " + (this.state.selected ? "" : "displayQua")}>Q: {this.state.quantity}</p>
</div>
<button onClick={this.toggleMenu} href="#" style={{width: 100 + '%', margin: 0+' '+'auto'}} className="btn">SELECT</button>
</div>
</div>
<div className="menu">
<div className={this.state.visible ? "" : "visible"}>
<div className="menu">
{_.times(this.props.quantity, i => (
<a onClick={this.targetValue} key={i} href="#">{i + 1}</a>
))}
</div>
</div>
</div>
</div>
The question you have asked is a bit unclear. But as far as I understand there could be 2 issues :
Change const quantities = [...this.state.quantities]; to let quantities = [...this.state.quantities]; since you'll be pushing new values to the array.
let qua = e.target.textContent; not sure if this is the best way to get the value. Try let qua = e.target.value; and pass the value param in anchor tag <a onClick={this.targetValue} value={i+1} key={i} href="#">{i + 1}</a>
Sharing the output for what you tried will definitely help to understand better.
The best way to push elements to a state array in React. You can do this
const newQuantity = {name: this.props.name, quantity: qua};
this.setState(previousState => ({
quantities : [...previousState.quantities, newQuantity]
}));
Also don’t use multiple setStates inside handler function use one that’s enough :)
Related
Im looking for a solution to build a Template website in React which displays a Carousel with 3 different Images on the Left Part and a Informational Part on the Right with A Title, some Attributes and a Description. I dont want to Copy and Paste the Website all the Time to rewrite every element and Change the Pictures. The Barebone of my Page is done, i just need the Solution to probably make an Array and depended on the Image which is clicked, youre getting to the mentioned DescriptionPage filled with the Information based on the clicked Image.
const DescriptionPage = () => {
return (
<>
<div className='CardDescriptionContainer'>
<Carousel>
<CarouselItem><img alt="Fool" className='image-carousel' src={Fool} draggable="false"/></CarouselItem>
<CarouselItem><img alt="Fool" className='image-carousel' src={ThothFool} draggable="false"/></CarouselItem>
<CarouselItem><img alt="Fool" className='image-carousel' src={JDFool} draggable="false"/></CarouselItem>
</Carousel>
<div className='CardDescription '>
<div className='Title'>
<h1>The Fool</h1>
</div>
<div className='Element'>
<h2>Element</h2>
<p>Air</p>
</div>
<div className='Zodiac'>
<h3>Zodiac / Planet</h3>
<p>Uranus</p>
</div>
<div className='Qualities'>
<h3>Qualities</h3>
<p>Freedom <br/>
Lust for Life<br/>
Beginnings<br/>
Adventure</p>
</div>
<div className='Symbols'>
<h3>Symbols</h3>
<p> White Rose <br/>
Small Bundle<br/>
Small Animal<br/>
Precipice</p>
</div>
<div className='ShortDescription'>
<h2>Description</h2>
<p>Into the Unkown.... this is placeholder Text for the Fool as he is, a Placeholder, the nothing before there is with all the Options to go anywhere and be anyone he'd like to. Pure AIR!</p>
</div>
</div>
</div>
</>
)
}
export default DescriptionPage
I was trying to find the Correct Syntax and was thinking about Mapping over an Array containing the Data but i dont know how to choose the correct Array or Dataset based on the clicked Image. Would i use useState to change the State of the Page itself or is it the best approach to "load" the Description Page with the Data stored in a different file?
You can write like this, if I understand you correctly
const INTIAL_VALUES = [
{
className: "Title",
heading: "The Fool",
paragraph: ""
},
{
className: "Element",
heading: "Element",
paragraph: "Air"
}, {
className: "Zodiac",
heading: "Zodiac / Planet",
paragraph: "Uranus"
}, {
className: "Qualities",
heading: "Qualities",
paragraph: "Freedom Lust for Life Beginnings Adventure"
}]
const DescriptionPage = () => {
const [state, setState] = useState(INTIAL_VALUES)
return (
<>
<div className='CardDescriptionContainer'>
<Carousel>
<CarouselItem><img alt="Fool" className='image-carousel' src={Fool} draggable="false" /></CarouselItem>
<CarouselItem><img alt="Fool" className='image-carousel' src={ThothFool} draggable="false" /></CarouselItem>
<CarouselItem><img alt="Fool" className='image-carousel' src={JDFool} draggable="false" /></CarouselItem>
</Carousel>
<div className='CardDescription '>
{state.map((element, key) => (<div key={key} className={element.className}>
<h3>{element.heading}</h3>
<p>{element.paragraph}</p>
</div>))}
</div>
</div>
</>
)
}
export default DescriptionPage
i am currently working on chat application with sockets , when i get different messages i use an array and then use map method to display them in simple html tags like p etc it worked perfect but inside text-area its not working i also tried to set text-area value property with map method but only i see is [object object] . also how can i automatically move the scroll bar down when messages there are more messages.
here is the code
import { Fragment, useEffect } from "react";
import { format } from "date-fns";
const Chat = ({ name, message }) => {
const date = new Date();
const hour = date.getHours();
const minute = date.getMinutes();
const second = date.getSeconds();
console.log("so bteay", message);
return (
<Fragment>
<div>
<h3 className="d-inline-block me-3"> Chat log </h3>
{name && (
<span className="me-3 d-inline-block">
<div
class="spinner-grow spinner-grow-sm text-success"
style={{ fontSize: "10px" }}
role="status"
>
<span class="visually-hidden">Loading...</span>
</div>
</span>
)}
<small className="text-muted d-block "> {name}</small>
<textarea
cols="70"
rows="8"
value={message.map((eachMsg) => {
return (
<Fragment>
{
<small className="text-muted d-inline-block">{`${hour}:${minute}:${second}`}</small>
}
<p
className="d-block shadow p-1 fw-bold rounded text-success"
style={{ fontFamily: "cursive" }}
>
{eachMsg}
</p>
</Fragment>
);
})}
></textarea>
</div>
</Fragment>
);
};
export default Chat;
You can only pass 1 child ( text in this case ) to text area. But you are trying to pass an array. If what you meant to do is to have as many as textareas as your array, this is how you should go about it:
const texts = ["Hi", "Bye","done"];
<div>
{texts.map((text) => (
<textarea>text</textarea>
))}
</div>
but if you are trying to have 1 textarea with all your texts inside it, first you need to create a long string using join method, and then render that string.
I think that you can't set html code inside textarea, unless you want to show it as a text?
** I want to change the image src on mouseover, i have added multiple images dynamically.**
const Servicesdata = [
{
ID: "01",
title: "Power Generation",
desc:
" We have rich experience in building thermal, hydro, and combined cycle power plants. We provide customized ready-to-deploy solutions for power plants including total EPC and comprehensive Balance of Plant (BOP) and Flue-gas desulfurization (FGD) solutions.",
imgsrc: "https://www.tataprojects.com/images/Transmission-Line.jpg",
imgsrcHover: "https://www.tataprojects.com/images/Sunbstations-min.jpg"
},
{
ID: "02",
title: "Transmission",
desc:
"We have successfully commissioned more than 13,000 kms of transmission lines across multiple voltage levels including 800kv HVDC projects",
imgsrc: "https://www.tataprojects.com/images/Sunbstations-min.jpg",
imgsrcHover: "https://www.tataprojects.com/images/Sunbstations-min.jpg"
},
{
ID: "03",
title: "Substations",
desc:
"Our optimally designed towers and substation structures allow us to reduce conductor wastage ensuring faster construction and on-time delivery.",
imgsrc: "https://www.tataprojects.com/images/Tower-Manufactaring-Unit.jpg",
imgsrcHover: "https://www.tataprojects.com/images/Sunbstations-min.jpg"
},
{
ID: "04",
title: "Tower Manufacturing Unit",
desc:
"We have a state-of-the-art manufacturing unit to manufacture transmission line towers and structures. The unit is spread across 40 acres of land.",
imgsrc: "https://www.tataprojects.com/images/Smart-Grid-min.jpg",
imgsrcHover: "https://www.tataprojects.com/images/Sunbstations-min.jpg"
}
];
export default Servicesdata;
import react from "react";
import Servicesdata from "../data/Servicesdata";
const Services = () => {
return (
<>
<section className="services">
<div className="container mt-5">
<div className="row">
<div className="col-md-12">
<h2 className="text-center heading-style-1">Key Areas</h2>
</div>
</div>
{Servicesdata.map((val, index) => {
return (
<div className="row featurette align-items-center">
<div className="col-md-7">
<h2 className="featurette-heading">{val.title}</h2>
<p className="lead">{val.desc}</p>
</div>
<div className="col-md-5">
<img src={val.imgsrc} className="img-fluid" />
</div>
</div>
);
})}
</div>
</section>
</>
);
};
export default Services;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
We can make use of onMouseOver & onMouseOut event handlers in order to toggle the images of the current hovering image.
We can store the ID of the object in the state when we hover on the image of that particular object
And reset it to "" on mouse out
In render we can check the ID in the state with the object id, if they are matching then use imgsrcHover else use imgsrc
const Servicesdata = [{ID:"01",title:"Power Generation",desc:" We have rich experience in building thermal, hydro, and combined cycle power plants. We provide customized ready-to-deploy solutions for power plants including total EPC and comprehensive Balance of Plant (BOP) and Flue-gas desulfurization (FGD) solutions.",imgsrc:"https://www.tataprojects.com/images/Transmission-Line.jpg",imgsrcHover:"https://www.tataprojects.com/images/Sunbstations-min.jpg"},{ID:"02",title:"Transmission",desc:"We have successfully commissioned more than 13,000 kms of transmission lines across multiple voltage levels including 800kv HVDC projects",imgsrc:"https://www.tataprojects.com/images/Sunbstations-min.jpg",imgsrcHover:"https://www.tataprojects.com/images/Sunbstations-min.jpg"},{ID:"03",title:"Substations",desc:"Our optimally designed towers and substation structures allow us to reduce conductor wastage ensuring faster construction and on-time delivery.",imgsrc:"https://www.tataprojects.com/images/Tower-Manufactaring-Unit.jpg",imgsrcHover:"https://www.tataprojects.com/images/Sunbstations-min.jpg"},{ID:"04",title:"Tower Manufacturing Unit",desc:"We have a state-of-the-art manufacturing unit to manufacture transmission line towers and structures. The unit is spread across 40 acres of land.",imgsrc:"https://www.tataprojects.com/images/Smart-Grid-min.jpg",imgsrcHover:"https://www.tataprojects.com/images/Sunbstations-min.jpg"}];
const { useState } = React;
const Services = () => {
//Store the currently hovered object's id in the state
//Initially it'll be ""
const [currentHoveredId, setCurrentHoveredId] = useState("");
//On mouse over update the id with the cuurent object's ID
const onMouseOver = (id) => {
setCurrentHoveredId(id);
}
//On moving the cursoe out of the image, then reset it to ""
const onMouseOut = () => {
setCurrentHoveredId("");
}
return (
<section className="services">
<div className="container mt-5">
<div className="row">
<div className="col-md-12">
<h2 className="text-center heading-style-1">Key Areas</h2>
</div>
</div>
{Servicesdata.map((val, index) => {
return (
<div className="row featurette align-items-center" key={val.ID}>
<div className="col-md-7">
<h2 className="featurette-heading">{val.title}</h2>
<p className="lead">{val.desc}</p>
</div>
<div className="col-md-5">
{/* Toggle the image source based on the result of the id in state and the id of the current object */}
<img src={currentHoveredId === val.ID ? val.imgsrcHover : val.imgsrc}
className="img-fluid"
onMouseOver={() => {onMouseOver(val.ID)}}
onMouseOut={onMouseOut}/>
</div>
</div>
);
})}
</div>
</section>
);
};
ReactDOM.render(<Services />, document.getElementById("react"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="react"></div>
I have used your code as it is just added the corresponding event handlers and the state as mentioned above.
Make the following modifications in the code:
this.setState({
servicesData: ServicesData;
})
And call the below function on mouseover,passing the index and the newSrc as parameter:
imgSrcUpdate(index, newSrc) {
let oldData = this.state.servicesData;
oldData[index][src] = newSrc;
this.setState({
servicesData: oldData
})
}
Instead of this:
{Servicesdata.map((val, index) => { ...
Use :
{this.state.servicesData.map((val, index) => {....
im currently working on a React JS App and i have an Array which has Objects in it, and inside the Objects it has Arrays.
Here's the code first,
constructor() {
super();
this.state = {
namaSantri: null,
examTitle: 'PLP BAHAS Arab Talaqqi',
examLevel: 0,
examType: 'Ujian 1 Tulis',
vocabQ: [{questionTitle: 'Question Title', question: ['Question 1', 'Question 2']}],
};
}
componentDidMount(){
var questionEx = {questionTitle: 'Question Title2', question: ['Question 1']}
var anotherArray = ['Question 2']
var addIndex = questionEx.question.concat(anotherArray)
this.setState({
vocabQ: [...this.state.vocabQ, addIndex]
})
}
So i have an Array whis is vocabQ here, and it contains Objects which contains my QuestionTitles and my Questions Array.
I want to create an input program for the Quesiton Object ( that contains questionTitle and questions ) here, so i tried to concat my array at addIndex but it show nothing. Help?
My render,
render() {
/**SOMETHING THAT YOU NEED TO WRITE TO OUTPUT AN ARRAY? */
const map = this.state.vocabQ.map((d) => <p key={d.questionTitle}>{d.questionTitle} {d.question}</p>);
return (
<div /**DIV PAGE START */
className="App">
<div /**DIV HEADER START */
className="DivHeader">
<Center>
<p className="ExamTitle">{this.state.examTitle}</p>
</Center>
<Center>
<p className="ExamLevel">Level {this.state.examLevel}</p>
</Center>
<Center>
<p className="ExamType">{this.state.examType}</p>
</Center>
<Center>
<div className="NameInput">
<InputText value={this.state.namaSantri} onChange={(e) => this.setState({value: e.target.namaSantri})} />
{/**HERE IS WHERE THE ARRAY SHOULD BE */}
<span> {map}</span>
</div>
</Center>
{/**DIV HEADER END */}
</div>
<div /**DIV VOCAB QUESTIONS START */>
{/**DIV VOCAB QUESTIONS END */}
</div>
{/**DIV PAGE END*/}
</div >
);
}
NB: It only show "Question Title Question 1Question 2"
image
Try it like this:
componentDidMount(){
var questionEx = {questionTitle: 'Question Title2', question: ['Question 1']}
var anotherArray = ['Question 2']
var addIndex = questionEx.question.concat(anotherArray)
this.setState({
vocabQ: [...this.state.vocabQ, ...addIndex] //<----This "..." is the part that has changed
})
}
You basically have to use the spread operator on both arrays in order for it to work the way you want to. Head to https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Operators/Spread_operatorhttps://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Operators/Spread_operator to learn a bit more about that.
I am trying to render image from array by placing its name in middle of <img> link.
At this time I have ran out of links that could help me...
I tried everything that came to my mind. Everything displays as it should except image...!
this is array:
cars: [
{
'carname': '2013 Toyota GT86',
'owner': 'Ryan',
'desc': 'Aero Paket, BC Coilover, 3sdm 0.01 black matte, Invidia N1 Catback, Valenti taillights, camouflage vinyls, Vortech supercharger incl. oil cooler - 325hp daily driver',
'image': 'toyota'
}]
Render section:
render() {
const cars = this.state.cars.map((car, i) => {
return (
<div key={i}>
<div className="col-md-12 cBusiness">
<h2>
{ car.carname }
</h2>
<p>Owner: { car.owner }</p>
<p>{ car.desc }</p>
<p>
<img src={"pages/upload/{car.image}.jpg"} />
</p>
</div>
</div>
);
});
structure:
Do something like this:
<img src={`pages/upload/${car.image}.jpg`} />
Try using template literals:
<img src={`pages/upload/${car.image}.jpg`} />
or old skool for all the IE folks out there:
<img src={"pages/upload/" + car.image + ".jpg"} />
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals