I have this JSON data in another file:
{
"feed": [
{
"id": 1,
"text": "Hey everyone I'm looking for help with my meditation, when does everyone do it?",
"messages": [
{
"id": 1,
"text": "I like to do it first thing in the morning and sometimes at night!",
},
{
"id": 2,
"text": "Thanks I'll try that!",
}
]
},
{
"id": 2,
"text": "Have you tried a weighted blanket?",
"messages": [
{
"id": 3,
"text": "Yeah, they're great, I have the 10lb one!",
},
{
"id": 4,
"text": "Thank you!",
}
]
}
]
}
I successfully rendered the two sets of data under "feed" using the map function by doing this:
<div>
{Data.feed.map(feed => {
return(
<>
<h4>{ feed.id }</h4>
<p>{ feed.text }</p>
</>
)})
}
</div>
My question is: how do I also render the inner messages loop? I was told to use a nested .map and here's what I unsuccessfully attempted:
<div>
{Data.feed.map(feed => {
return {feed.messages.map(messages => {
return (
<>
<h4>{ feed.id }</h4>
<p>{ feed.text }</p>
<h5>{ messages.id }</h5>
<p>{ messages.text }</p>
</>
)}
)}
})}
</div>
You were actually close. You currently loop over the feed array only. You need to use a second map() to iterate over the messages too inside every item of the feed.
Check out the snippet below:
function App() {
return (
<div>
{data.feed.map((feed) => (
<React.Fragment key={feed.id}>
<h4>{feed.id}</h4>
<p>{feed.text}</p>
<ul>
{feed.messages.map((message) => (
<li key={message.id}>{message.text}</li>
))}
</ul>
</React.Fragment>
))}
</div>
);
}
const data = {
feed: [
{
id: 1,
text:
"Hey everyone I'm looking for help with my meditation, when does everyone do it?",
messages: [
{
id: 1,
text:
'I like to do it first thing in the morning and sometimes at night!',
},
{
id: 2,
text: "Thanks I'll try that!",
},
],
},
{
id: 2,
text: 'Have you tried a weighted blanket?',
messages: [
{
id: 3,
text: "Yeah, they're great, I have the 10lb one!",
},
{
id: 4,
text: 'Thank you!',
},
],
},
],
};
ReactDOM.render(<App />, document.querySelector('#root'));
<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>
<div id="root"></div>
Related
There is a JSON for categories with the following structure
[
{
"category": "Mobiles",
"sub": [
{
"name": "Apple"
},
{
"name": "Samsung"
}
]
},
{
"category": "Televisions",
"sub": [
{
"name": "Lg"
},
{
"name": "Sony"
}
]
}
]
First i load data from backend to a variable called categories (On the backend side im using expressjs and pass data with res.json(JSON.parse(fs.readFileSync('categories.json')))
I want to iterate through categories sub category with
{categories.map(function (category, i) {
return (
<>
<h6 Key={i}>{category.category}</h6> //For example: <h6>Mobiles</h6>
<>... [logic to iterate the current category's sub categories] ...</> //For example: <p>Apple</p> <p>Samsung</p>
</>
);
})}
I tried to use a second map on category.sub like category.sub.map((s,j)=><p Key={j}>{s.name}</p>) but unfortunely i can't get it work, and I can't describe my problem to Google in English so it can be an easy answer and i am the big L
Any help?
Thanks
Try this, uncomment out the console.log to verify data if screen is white.
return (
<>
{categories.map(function (category, i) {
// console.log(category.category );
// console.log(category.sub );
return (
<>
<h6 key={i}>{category.category}</h6>
<>
{category.sub.map(function (sub, j) {
// console.log(category.category + '' + sub.name);
return <p key={j}> {sub.name}</p>;
})}
</>
</>
);
})}
</>
);
Data:
let categories = [
{
category: 'Mobiles',
sub: [
{
name: 'Apple',
},
{
name: 'Samsung',
},
],
},
{
category: 'Televisions',
sub: [
{
name: 'Lg',
},
{
name: 'Sony',
},
],
},
];
I tried to use multiple tabs in react. But it doesn't seem working (please see the picture). I 'm not able to display the header for my Tabs neither the body (from match.json) that should contained a textbox field as input...
import React from "react";
import { Tab, Tabs as TabsComponent, TabList, TabPanel } from "react-tabs";
import "react-tabs/style/react-tabs.css";
const Tabs = ({ data }) => (
<TabsComponent>
<TabList>
{data.map(({ name }, i) => (
<Tab key={i}>{name}</Tab>
))}
</TabList>
{data.map(({ name }, i) => (
<TabPanel key={i}>{name}</TabPanel>
))}
</TabsComponent>
);
export default Tabs;
MenuItemDisplay:
export default function MenuItemDisplay() {
const { match } = JsonData;
...
<Tabs data={match.questions[0]} />
</div>
</>
);
}
match.json :
{
"match": [
{
...
"_ids": [
"questions": [
{
"name": "Tell me about yourself ",
"typeProof": ""
},
...
],
]
}
]
}
The data that you want to send to the Tabs component is the currently matched item's questions array.
const { menuId, itemId } = useParams();
const { match } = JsonData;
const matchData = match.find((el) => el._id_menu === menuId)?._ids ?? [];
const item = matchData.find((el) => el._id === itemId);
Here item is the current menu item being rendered, "Pea Soup", or item "123ml66" for example:
{
"_id": "123ml66",
"name": "Pea Soup",
"description": "Creamy pea soup topped with melted cheese and sourdough croutons.",
"dishes": [
{
"meat": "N/A",
"vegetables": "pea"
}
],
"questions": [
{
"name": "Tell me about yourself ",
"typeProof": ""
},
{
"name": "Why our restaurant?",
"typeProof": ""
},
{
"name": "What hours are you available to work ?",
"typeProof": "Planning"
}
],
"invited": [
{
"name": "Jose Luis",
"location": "LA"
},
{
"name": "Smith",
"location": "New York"
}
],
"taste": "Good",
"comments": "3/4",
"price": "Low",
"availability": 0,
"trust": 1
},
Pass item.questions to the Tabs component.
<Tabs data={item.questions} />
...
const Tabs = ({ data }) => (
<TabsComponent>
<TabList>
{data.map(({ name }, i) => (
<Tab key={name}>Question {i + 1}</Tab>
))}
</TabList>
{data.map(({ name }) => (
<TabPanel key={name}>{name}</TabPanel>
))}
</TabsComponent>
);
I am trying to map parent comments and then within the map function I want to map the corresponding nested child comments that are only one level deep.
For some reason when I try to do this all the nested child comments display below the first parent comment.
I have two arrays:
parentComments: [
{
id: "1",
comment: "First parent comment"
},
{
id: "2",
comment: "Second parent comment"
},
]
childComments: [
{
id: "3",
comment: "First child comment",
parentCommentId: "1"
},
{
id: "4",
comment: "Second child comment",
parentCommentId: "2"
},
]
Here is the code I am trying:
{parentComments.map((parentComment) => (
<ul>
{parentComment.comment}
<li>
{" "}
{childComments.map((childComment) => (
<>
{childComments.find(
(e) => e.parent_comment_id === comment.id
)
? childComment.comment
: ""}
</>
))}
</li>
</ul>
))}
What I would expect to happen is each parent comment is mapped through, if a child comments parentCommentId equals the id of the parent comment being mapped, it would display the child comment below it.
At first make new array like this then
let parentComments =[
{
id: "1",
comment: "First parent comment"
},
{
id: "2",
comment: "Second parent comment"
},
]
let childComments= [
{
id: "3",
comment: "First child comment",
parentCommentId: "1"
},
{
id: "4",
comment: "Second child comment",
parentCommentId: "2"
},
];
let mapArray =parentComments.map(p => ({
...p,
childComments : childComments.filter(c => c.parentCommentId ==p.id)
}));
console.log(mapArray);
<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>
then you can try
{parentComments.map((parentComment) => (
<ul>
{parentComment.comment}
<li>
{" "}
{childComments.map((childComment) => (
<>
childComment.comment
}
</>
))}
</li>
</ul>
))}
When I use map() to return the names of devices in my database, it only returns the first name.I am not very confident with JavaScript so this may be a simple issue.
Here's my database:
[{
"dwelling_id": 1,
"rooms": [{
"room_id": 1,
"room_name": "Living Room",
"devices": [{
"id": 1,
"device_name": "Google Home",
}]
},
{
"room_id": 2,
"room_name": "BedRoom",
"devices": [{
"id": 2,
"device_name": "Smart Bulb 1",
}]
}...
Here's the code to return both Google Home and Smart Bulb in separate Bootstrap Cards:
{props.house.map(house => {
return (
<React.Fragment>
<Card>
<Card.Body>
<Card.Title>
{house.rooms[0].devices[0].device_name}
</Card.Title>
</Card.Body>
</Card>
</React.Fragment>
)}
})}
If I do this:
// If I change this...
{house.rooms[0].devices[0].device_name}
// to...
{house.rooms[1].devices[0].device_name}
My code only returns just Smart Bulb.
Note that I want to return both Google Home and Smart Bulb in two separate Cards.
Any help would be greatly appreciated, thank you!
You need to do a second and third .map inside our first map in order to return both rooms:
{props.house.map(house => {
return (
<React.Fragment>
<Card>
<Card.Body>
{
house.rooms.map((room) => (
room.map((device) => (
<Card.Title>{device.device_name}</Card.Title>
)
)
}
</Card.Body>
</Card>
</React.Fragment>
)
}
})}
You have 2 levels in your array, when you do props.house.map, you only get the first level object: dwelling. If you want to list all the rooms of a dwelling, then you need to make a second map like this:
props.house.map(dwelling => {
dwelling.map(room => {
console.log(room.devices[0].device_name);
}
})
I have a form that displays customer data based on a JSON object received from an initial GET request. I map that information out to display both the customer details and their available offers and I've created an onClick function to highlight their selected offer which maps offerId to an object I've defined in state called cardActive. What I'm trying to do now is create a second onClick function connected to a submit button that fires a POST action returning the following values as the JSON body:
{
"CustomerId" : "1",
"SessionId" : "9636",
"Offer": {
"OfferId" : "1",
"OfferName" : "Business Internet 75"
}
}
I've included my current component below including a dummy JSON object that mimics the response back from that initial GET request
class UsersList extends Component {
constructor() {
super();
this.selectCard = this.selectCard.bind(this);
this.state = {
cardActive: null,
offerName: null,
customerId: null,
customers: [
{
CustomerId: "1",
LastName: "Doe",
FirstName: "Jane",
Address: {
Address1: "1811 Chestnut Street",
Address2: null,
City: "Philadelphia",
State: "Pennsylvania",
Zip: "19103"
},
Offers: [
{
OfferId: "Offer1",
Name: "Offer Number 1",
Products: [
{
ProductId: 1,
ProductName: "Cool stuff"
},
{
ProductId: 2,
ProductName: "Some little stuff"
}
],
Price: "$1"
},
{
OfferId: "Offer2",
Name: "Offer Number 2",
Price: "$2",
Products: [
{
ProductId: 3,
ProductName: "More stuff"
},
{
ProductId: 4,
ProductName: "Hey theres stuff here"
}
]
},
{
OfferId: "Offer3",
Name: "Offer Number 3",
Price: "$3",
Products: [
{
ProductId: 5,
ProductName: "Check out this stuff"
},
{
ProductId: 5,
ProductName: "More stuff"
}
]
}
]
}
]
};
}
selectCard(offerId) {
this.setState({ cardActive: offerId });
}
render() {
return (
<div>
{this.state.customers.map((customer, index) => {
return (
<div key={index + customer.CustomerId}>
<h3>
Name: {customer.LastName}, {customer.FirstName}
</h3>
<h3>Customer ID: {customer.CustomerId}</h3>
<h3>
Address:
<br />
{customer.Address.Address1}
<br />
{customer.Address.City}, {customer.Address.State}{" "}
{customer.Address.Zip}
</h3>
<br />
<h2>Available Offers</h2>
<Grid container spacing={24} justify="center">
{customer.Offers.map((Offer, index) => {
return (
<div
key={index + Offer.OfferId}
onClick={() => this.selectCard(Offer.OfferId)}
>
<Grid item xs={12}>
<div
className={
Offer.OfferId === this.state.cardActive
? "cardActive"
: "card"
}
>
<div className="container">
<h5>
<b>{Offer.OfferId}</b>
</h5>
<h2>{Offer.Name}</h2>
{Offer.Products.map((Product, index) => {
return (
<div key={index + Product.ProductId}>
<p>+ {Product.ProductName}</p>
</div>
);
})}
<h3>{Offer.Price}</h3>
</div>
</div>
</Grid>
</div>
);
})}
</Grid>
</div>
);
})}
<button className="navbuttonSelected">Submit</button>
</div>
);
}
}
export default UsersList;
I added the objects into the state that I'm hoping to populate (offerName, CustomerId and keeping cardActive as the holder for offerId) and now I'm trying to figure out how to write the function to map all of those values to send back via POST. The best I've come up with so far is
submitSelection(offerId, offerName, CustomerId) {
this.setState({
cardActive: offerId,
offerName: offerName,
CustomerId,
SessionId: SessionId
});
}
Any suggestions/examples on how to do this would be a huge help
I think that the best way to handle the data form is by a state property in this case will be something like this :
this.state = {
dataModel:{
cardActive : null,
offerName : null,
customerId : null,
CustomerId : null,
SessionId : null,
},
...
}
]
};
So in your submit function you can just update the data that youve received to the this.state.dataModel.
then you can use axios or somthing to send the dataModel to as the data of the axios method.
Check my sandbox maybe is clearer that way:
https://codesandbox.io/s/8xm00xplm2