Order by nested field using Astro - javascript

Given the following JSON response, how would I group them according to team first, then by year, using javascript and/or jsx to map the response? I'm using Astro.
{
"data": [
{
"id": 1,
"team_name": "Team One",
"players": [
{
"player_name": "Mickey Mantle",
"players_year": {
"year": 2024
}
},
{
"player_name": "Larry Smalls",
"players_year": {
"year": 2022
}
},
{
"player_name": "Ron Davis",
"players_year": {
"year": 2024
}
}
]
},
{
"id": 2,
"team_name": "Team Two",
"players": [
{
"player_name": "Jim Abbot",
"players_year": {
"year": 2022
}
}
]
}
]
}
End Result – The HTML output should match this:
<div class="group">
<h2>Team One</h2>
<h3>2022</h3>
<ul>
<li>Larry Smalls</li>
</ul>
<h3>2024</h3>
<ul>
<li>Mickey Mantle</li>
<li>Ron Davis</li>
</ul>
</div>
<div class="group">
<h2>Team Two</h2>
<h3>2022</h3>
<ul>
<li>Jim Abbot</li>
</ul>
</div>
Currently, here is my file which works, but without the grouping as seen directly above. What additional javascript is needed in Astro's frontmatter and markup required in the body of the page?
teams.astro
---
const directus = await getDirectusClient()
const response = await directus.items("teams").readByQuery({
fields: [
"id",
"team_name",
"players.player_name",
"players.players_year.year",
],
})
const formattedResponse = response.data.map((team) => {
return {
...team,
yearsArr: team.players.map(player => player.players_year.year)
}
})
const [...teams] = formattedResponse
---
<h1>Teams Page</h1>
{
teams.map((team) => {
return (
<div class='group'>
<h2>{team.team_name}</h2>
<ul>
{team.players.map((player) => (
<li>
{player.player_name} ({player.players_year.year})
</li>
))}
</ul>
</div>
)
})
}

This have been asked many times before. But not exactly like this.
Update: added the html markup (for Astro).
var obj = {data:[{id:1,team_name:"Team One",players:[{player_name:"Mickey Mantle",players_year:{year:2024}},{player_name:"Larry Smalls",players_year:{year:2022}},{player_name:"Ron Davis",players_year:{year:2024}}]},{id:2,team_name:"Team Two",players:[{player_name:"Jim Abbot",players_year:{year:2022}}]}]};
var result = {};
obj.data.forEach(function(item) {
result[item.team_name] = result[item.team_name] || {}
item.players.forEach(function(player) {
result[item.team_name][player.players_year.year] = result[item.team_name][player.players_year.year] || [];
result[item.team_name][player.players_year.year].push(player.player_name);
})
})
console.log(result)
.as-console-wrapper {
max-height: 100% !important
}
<h1>Teams Page</h1>
{Object.entries(result).map(([team_name, team]) => { return (
<div class='group'>
<h2>{team_name}</h2>
{Object.entries(team).map(([year, players]) => (
<h3>{year}</h3>
<ul>
{players.map(player_name) => (
<li>
{player_name}
</li>
)}
</ul>
))}
</div>
) }) }

Related

REACT- Multiple Tabs don't work, headers and body don't diplayed

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>
);

Recursively render list of items based on the API response

I have a list of items that needs to be recursively rendered. I am able to render it upto first level. Can someone help me with the nested recursion. I have posted the relevant functions in a function component. Note that details has been stored in a state variable details
{
"details": [{
"title": "Part-1",
"content": [{
"type": "text",
"content": "TextABC"
}]
}, {
"title": "Part-2",
"content": [{
"type": "text",
"content": "TextXYZ"
}, {
"type": "list",
"content": [{
"text": "TextLMN",
"type": "text"
}, {
"type": "list",
"content": [{
"text": "TextPQR",
"type": "text"
}, {
"text": "TextDEF",
"type": "text"
}]
}]
}]
}, {
"title": "Part-3",
"content": [{
"type": "list",
"content": ["<a target='_blank' href='https://www.example.com'>ABC<\/a>", "<a target='_blank' href='https://www.example1.com'>XYZ<\/a>"]
}]
}]
}
Each Item is referenced either with a type that can be text or a list. I have tried the following, but the items with nested list is not working
const isAnchor = str => {
return /^\<a.*\>.*\<\/a\>/i.test(str);
};
const getContentJsx = (value) => {
return isAnchor(value) ? (
<li dangerouslySetInnerHTML={{ __html: sanitize(value) }} />
) : (
<li>{value}</li>
);
};
const getDetailJsx = () => {
return details.map(({ title, content }, index) => {
return (
<div key={`${title}${index}`}>
<h6>
<span>{title}</span>
</h6>
{content?.map(({ type: mainType, content: data }) => (
<div>
{mainType === "text" && <p>{data}</p>}
{mainType === "list" && <ul>{data?.map((contentValue) => getContentJsx(contentValue))}</ul>}
</div>
))}
</div>
);
});
};
return (
<div>
<>
{getDetailJsx()}
</>
)}
</div>
);
As suggested, you can create a recursive component that wraps the logic and makes it possible to call recursively. First, I had to correct your detail object. It has inconsistency within its attributes. Note, for example, text -> content:
"type": "text",
"text": "TextPQR"
to
"type": "text",
"content": "TextPQR"
Moreover, observe that it was separated the part that involves the title from the recursion to facilitate its comprehension and make code cleaner.
const getContentJsx = (value) => {
return isAnchor(value) ? (
<li dangerouslySetInnerHTML={{ __html: sanitize(value) }} />
) : (
<li>{recursive(value)}</li>
);
};
const getDetailJsx = () => {
return details.map(({ title, content }, index) => {
return (
<div key={`${title}${index}`}>
<h3>
<span>{title}</span>
</h3>
{recursive(content)}
</div>
)
})
}
const recursive = (content) => {
return (
<div>
{
content.map(({type: mainType, content: data}, index) => (
<div key={index}>
{mainType === "text" && <p>{data}</p>}
{mainType === "list" && <ul>{getContentJsx(data)}</ul>
}
</div>
))
}
</div>
)
Also as shown here

How to return all elements from an Object?

There is a page where you can see the details of a user's loan. There is a decorator where I return values ​​using the get () method. In general, there is a partial refund, which returns items of partial payments as shown in the photo. My problem is that I cannot specify all partial payments, only receive one by one.
Loan Details component:
<div className="ClientLoanDetails__card__content__inner__wrapper">
{Object.keys(payments[0]).map(val => {
{
[payments[0][val]].map((payment: any, index: number) => (
<div className="ClientLoanDetails__card__content-inner" key={index}>
{paymentsFields.map((item, indexInner) => (
<div className="ClientLoanDetails__card__content-item" key={indexInner}>
<div className="ClientLoanDetails__card__content-item__title">
{item.title}
</div>
<div className="ClientLoanDetails__card__content-item__value">
{payment[item.key]}
</div>
</div>
))}
</div>
));
}}
)
}}
</div>
This is code snippet for key & titles from loan.ts:
export const repaymentsFields = [
{
key: 'issuedDate',
title: lang.CLIENTS.REPAYMENTS.ISSUED_DATE,
},
{
key: 'period',
title: lang.CLIENTS.REPAYMENTS.PERIOD_IN_DAYS,
},
]
JSON of repayments:
"partialRepayments": [
{
"orderId": "A11Fz090VT1BmObJ0S-0",
"repaidPrincipalAmount": {
"amount": 250000.0
},
"repaidInterestAmount": {
"amount": 0
},
"repaidOverdueAmount": {
"amount": 0
},
"repaidProlongationAmount": {
"amount": 0
},
"started": "2020-11-09T16:52:08.981+0600",
"completed": "2020-11-09T16:52:21.170+0600",
"period": 25,
"timestamp": "2020-11-09T16:52:21.174+0600"
},
{
"orderId": "A11Fz090VT1BmObJ0S-1",
"repaidPrincipalAmount": {
"amount": 300000.0
},
"repaidInterestAmount": {
"amount": 0
},
"repaidOverdueAmount": {
"amount": 0
},
"repaidProlongationAmount": {
"amount": 0
},
"started": "2020-11-09T16:54:31.923+0600",
"completed": "2020-11-09T16:54:46.313+0600",
"period": 25,
"timestamp": "2020-11-09T16:54:46.317+0600"
}
],
the problem is that it is impossible to display the values ​​that come as in the photo (one loan may have several repayments)
I have to return all values from an Object
IMAGE of console
Why don't you loop through the partialPayementResponse and access each field through the dot . notation ? Such as follows:
<div>
{partialRepayments.map((item, index) => {
return (
<div key={index}>
<div>Completed: <span>{item.completed}</span></div>
<div>orderId: <span>{item.orderId}</span></div>
<div>period: <span>{item.orderId}</span></div>
<div>repaidInterestAmount: <span>{item.repaidInterestAmount.amount}</span></div>
<div>repaidOverdueAmount: <span>{item.repaidOverdueAmount.amount}</span></div>
<div>repaidPrincipalAmount: <span>{item.repaidPrincipalAmount.amount}</span></div>
<div>repaidProlongationAmount: <span>{item.repaidProlongationAmount.amount}</span></div>
<div>started: <span>{item.started}</span></div>
<div>timestamp: <span>{item.timestamp}</span></div>
</div>)
})}
</div>
I wrote it without using your classNames but I think you get the idea
Not sure what's the problem here.
Can't u just iterate over these things?
Or create function and then display the thing that function returns...
for example:
displayAppropriateFields = () => {
let returnedArray = [];
returnedArray.push(<div> Some text in the div </div>);
for(let i=0; i<someArray.length; i++) {
returnedArray.push(<span> someArray[i] </span>)
}
return returnedArray;
}
And then display it in render method like so:
this.displayAppropriateFields();

how to use filter effect on checkbox in ReactJS?

how to use filter-effect whenever user click on checkbox?
As per below image, there is filter page. what i am trying to do is whenever user will click on checkbox the value should be return as output as per below filtering api data, But i am getting a null value instead.
image:
end-point url : http://localhost:8000/api/filter/
filter category api-data:
{
"product_categoryData": [
{
"id": 1,
"category_title": "category01"
},
{
"id": 2,
"category_title": "category02"
},
],
"filter_colorData": [
{
"id": 1,
"color_title": "black",
"color_hex_code": "#000000"
},
{
"id": 2,
"color_title": "red",
"color_hex_code": "#43243dsf"
},
],
//(so on...)
}
After filtering product filter api-data,
end point-url: http://localhost:8000/api/p_list?product_category=1&min_price=&max_price=&color=&size=
[
{
"url": "http://localhost:8000/api/p/product01",
"id": 1,
"title": "product01",
"slug": "product01",
"image": "http://localhost:8000/media/product2_EMWEgQI.png",
"price": 5,
"status": true,
"created_on": "2020-04-19T18:44:03Z"
},
{
"url": "http://localhost:8000/api/p/product07",
"id": 8,
"title": "product07",
"slug": "product07",
"image": "http://localhost:8000/media/product4_CKX7xsA.png",
"price": 8,
"status": true,
"created_on": "2020-04-19T18:44:03Z"
}
]
./src/Filter.js
import React, { Component } from "react";
class App extends Component {
constructor(props) {
super(props);
this.state = {
response: "",
filter_response: "",
category_value : "",
min_price: "",
max_price: "",
color_value: "",
size_value: "",
};
}
componentDidMount() {
this.fetchData();
}
filterClick = (value) => {
this.setState({category_value: value, min_price: value, max_price: value, color_value: value,
size_value: value}, this.fetchFilterEffectData);
};
fetchData = async () => {
try {
const response = await fetch(
`http://localhost:8000/api/filter/`
);
const JsonResponse = await response.json();
this.setState({ response: JsonResponse });
}
catch (error) {
console.log(error);
}
};
fetchFilterEffectData = async () => {
try {
const filter_response = await fetch(
`http://localhost:8000/api/p_list?product_category=${this.state.category_value}&min_price=${this.state.min_price}&max_price=${this.state.max_price}&color=${this.state.color_value}&size=${this.state.size_value}`
);
const JsonFilterResponse = await filter_response.json();
this.setState({ filter_response: JsonFilterResponse });
}
catch (error) {
console.log(error);
}
};
render() {
const { response } = this.state;
if (!response) {
return "Loading...";
}
return (
<div>
//Before Effect
<div class="select_option_list">Category <i class="right fas fa-caret-down"></i> </div>
<div class="select_option_dropdown">
{response.product_categoryData.map((response) =>(
<div class="form-check form-check-outline">
<input class="form-check-input" type="checkbox" id="inlineCheckbox1" value="option1"/>
<label class="form-check-label" for="inlineCheckbox1"><a href="#" onClick={() => this.filterClick(response.id)}>{response.category_title}</a></label>
</div>
))}
</div>
</div>
//After Effect
{filter_response.map((response) =>(
<div class="col-md-12">
<div class="blog-entry animate d-md-flex">
<img src={response.image} className="App-logo"/>
<div class="text text-2 pl-md-4">
<h3 class="mb-2">{response.title}</h3>
</div>
</div>
</div>
))}
</div>
);
}
}
export default App;

Try to map over an array of url images to render to cards using map

As the title says I am trying to map over an array of objects to get the photo urls to render in the cards. The cards only populate when you fill out a review form. I tried faker js but it would render a blank image so I thought that an array of objects would do the trick but I keep getting the error "Objects are not valid as a React child (found: object with keys {id, img}). If you meant to render a collection of children, use an array instead." Not really sure I know what I am doing wrong. Please assistance would be appreciated.
import { Card, Image } from 'semantic-ui-react'
import { Link } from 'react-router-dom';
import { axiosWithAuth } from '../utils/auth'
import "./userInfo.css"
function UserCard(props) {
// console.log("cardprops", props)
const { setReviews } = props;
// const deleteReview = data => {
// console.log(data.id);
// setReviews(reviews => [...reviews.filter(review => review.id !== data.id)]);
// };
const deleteReview = restaurant => {
axiosWithAuth().delete(`https://foodiefun-api.herokuapp.com/api/reviews/${restaurant.id}`, restaurant)
.then(res => {
setReviews(reviews => [...reviews.filter(review => review.id !== restaurant.id)]);
})
.catch(err => {
console.log('can not delete message', err)
})
}
let postsdata = [
{
"id": 1,
"img": "https://www.thegrilledcheesetruck.com/wp-content/uploads/2017/03/gct-menu21-800x600.jpg"
},
{
"id": 2,
"img": "https://blueprint-api-production.s3.amazonaws.com/uploads/card/image/917437/3261d336-f53b-44a0-abdb-69792f60af66.jpg"
},
{
"id": 3,
"img": "https://tastychomps.com/wp-content/uploads/2019/06/P6150451-800x600.jpg"
},
{
"id": 4,
"img": "https://cdn.styleblueprint.com/wp-content/uploads/2019/07/SB-BHM-Food-Truck-Mustard-Seed-Food-Co-hot-mess-fries.jpg"
},
{
"id": 5,
"img": "https://snworksceo.imgix.net/cav/8ed1b226-a90d-4c2d-9216-99689efa4334.sized-1000x1000.jpg?w=800"
},
{
"id": 6,
"img": "https://www.whatsonnetwork.co.uk/uploads/800x600/e6e34f13ec62f43638b808feb55fab9e.jpg"
},
{
"id": 7,
"img": "https://news.wbfo.org/sites/wbfo/files/styles/medium/public/201907/table_food.jpg"
},
{
"id": 8,
"img": "https://craftcleaver.co.uk/wp-content/uploads/2017/10/sharing-platter-on-blue-square-angle-800x600.jpg"
},
{
"id": 9,
"img": "https://theculturetrip.com/wp-content/uploads/2015/12/800px-Hoppers_at_house_of_dosas.jpg"
},
{
"id": 10,
"img": "https://s3-prod.adage.com/s3fs-public/styles/800x600/public/80_ChickenMcNuggetHappyMeal.jpg"
},
{
"id": 11,
"img": "https://porteliotfestival.com/wp-content/uploads/2017/04/Port-Eliot-Festival-2017-294A3665-800x600.jpg"
},
{
"id": 12,
"img": "https://www.mykadhai.com/assets/images/img-4142-2000x1500-800x600.jpg"
},
{
"id": 13,
"img": "https://nwatravelguide.com/wp-content/uploads/2018/05/The-Hive-800x600.jpg"
},
{
"id": 14,
"img": "https://www.mjseatery.com/images/buritto.jpg"
},
{
"id": 15,
"img": "https://imagevars.gulfnews.com/2019/07/18/Deccan-Delight-biryani_16c043a76bd_original-ratio.jpg"
}
]
return (
<Card>
<div className="rating">
<span>☆</span><span>☆</span><span>☆</span><span>☆</span><span>☆</span>
</div>
const Photo = ({postsdata}) => (
<div>
{postsdata.map(postdata => (
<Image className='photoOfOrder' key={postdata.img} src={postdata.img} wrapped ui={false} />
))}
</div>
)
<Card.Content>
<Card.Header
className='restaurantName'>{props.tileData.restaurantName}
</Card.Header>
<Card.Meta>
<span className='dateOfVisit'><b>Date Visited: </b> {props.tileData.dateOfVisit}</span>
</Card.Meta>
<Card.Meta>
<span className='restaurantType'><b>Type of Food: </b>{props.tileData.restaurantType}</span>
</Card.Meta>
<Card.Meta>
<span className='waitTime'><b>Wait Time: </b>{props.tileData.waitTime} minutes</span>
</Card.Meta>
<Card.Meta>
<span className='menuItem'><b>Item Ordered: </b>{props.tileData.menuItem}</span>
</Card.Meta>
<Card.Meta>
<span className='price'><b>Price: $</b>{props.tileData.price}</span>
</Card.Meta>
<Card.Meta>
<span className='foodRating'><b>Food rating: </b>{props.tileData.foodRating} Stars</span>
</Card.Meta>
<Card.Meta>
<span className='comments'><b>Comments: </b>{props.tileData.comments}</span>
</Card.Meta>
</Card.Content>
<Link to={`/edit/${props.tileData.id}`}>
<button className='edit-btn btn btn-bubble'>
Edit
</button></Link>
<button className='delete-btn btn2 btn-bubble2'
onClick={() => deleteReview(props.tileData)}>
Delete
</button>
</Card >
)
}
export default UserCard;```
UderInfo.js
The only other file for the cards
```import React, { Component } from 'react';
import UserCard from './userCard';
import SearchSelect from './SearchSelect'
import "./userInfo.css";
export default class userInfo extends Component {
constructor(props) {
super(props);
this.state = { selectedFilterThingies: [] }
this.searchSelectHandler = this.searchSelectHandler.bind(this);
}
searchSelectHandler(value) {
this.setState({ selectedFilterThingies: value });
console.log("searched array", value)
}
// ["Fast Food", "Japanese", "Mexican" ]
render() {
//console.log("updatehandler", {this.searchSelectHandler})
if (!this.props.data) {
return <div>Loading Foodie Cards...</div>
}
else {
if (this.state.selectedFilterThingies.length < 1) {
return <section className='userCard '>
<div>
<div>
<SearchSelect updateHandler={this.searchSelectHandler} data={this.props.data} />
</div>
<div className='gridview' >
{this.props.data.map(oneRest => (
<UserCard className='onecard' tileData={oneRest} setReviews={this.props.setReviews} />
))}
</div>
</div>
</section>
}
else {
let newarray = []
//check for restuarant type and render from newarray
newarray = (this.props.data.filter(item =>
this.state.selectedFilterThingies.some(filter => filter === item.restaurantType)))
console.log("newarray", newarray)
return <section className='userCard '>
<div>
<div>
<SearchSelect updateHandler={this.searchSelectHandler} data={this.props.data} />
</div>
<div className='gridview'>
{newarray.map(oneRest => (
<UserCard className='onecard' tileData={oneRest} setReviews={this.props.setReviews} />
))}
</div>
</div>
</section>
}
}
}
}
```
you need to take Photo out of return statement and format map properly
import { Card, Image } from 'semantic-ui-react'
import { Link } from 'react-router-dom';
import { axiosWithAuth } from '../utils/auth'
import "./userInfo.css"
function UserCard(props) {
// console.log("cardprops", props)
const { setReviews } = props;
// const deleteReview = data => {
// console.log(data.id);
// setReviews(reviews => [...reviews.filter(review => review.id !== data.id)]);
// };
const deleteReview = restaurant => {
axiosWithAuth().delete(`https://foodiefun-api.herokuapp.com/api/reviews/${restaurant.id}`, restaurant)
.then(res => {
setReviews(reviews => [...reviews.filter(review => review.id !== restaurant.id)]);
})
.catch(err => {
console.log('can not delete message', err)
})
}
let postsdata = [
{
"id": 1,
"img": "https://www.thegrilledcheesetruck.com/wp-content/uploads/2017/03/gct-menu21-800x600.jpg"
},
{
"id": 2,
"img": "https://blueprint-api-production.s3.amazonaws.com/uploads/card/image/917437/3261d336-f53b-44a0-abdb-69792f60af66.jpg"
},
{
"id": 3,
"img": "https://tastychomps.com/wp-content/uploads/2019/06/P6150451-800x600.jpg"
},
{
"id": 4,
"img": "https://cdn.styleblueprint.com/wp-content/uploads/2019/07/SB-BHM-Food-Truck-Mustard-Seed-Food-Co-hot-mess-fries.jpg"
},
{
"id": 5,
"img": "https://snworksceo.imgix.net/cav/8ed1b226-a90d-4c2d-9216-99689efa4334.sized-1000x1000.jpg?w=800"
},
{
"id": 6,
"img": "https://www.whatsonnetwork.co.uk/uploads/800x600/e6e34f13ec62f43638b808feb55fab9e.jpg"
},
{
"id": 7,
"img": "https://news.wbfo.org/sites/wbfo/files/styles/medium/public/201907/table_food.jpg"
},
{
"id": 8,
"img": "https://craftcleaver.co.uk/wp-content/uploads/2017/10/sharing-platter-on-blue-square-angle-800x600.jpg"
},
{
"id": 9,
"img": "https://theculturetrip.com/wp-content/uploads/2015/12/800px-Hoppers_at_house_of_dosas.jpg"
},
{
"id": 10,
"img": "https://s3-prod.adage.com/s3fs-public/styles/800x600/public/80_ChickenMcNuggetHappyMeal.jpg"
},
{
"id": 11,
"img": "https://porteliotfestival.com/wp-content/uploads/2017/04/Port-Eliot-Festival-2017-294A3665-800x600.jpg"
},
{
"id": 12,
"img": "https://www.mykadhai.com/assets/images/img-4142-2000x1500-800x600.jpg"
},
{
"id": 13,
"img": "https://nwatravelguide.com/wp-content/uploads/2018/05/The-Hive-800x600.jpg"
},
{
"id": 14,
"img": "https://www.mjseatery.com/images/buritto.jpg"
},
{
"id": 15,
"img": "https://imagevars.gulfnews.com/2019/07/18/Deccan-Delight-biryani_16c043a76bd_original-ratio.jpg"
}
]
const Photo = postsdata.map(postdata => (
<Image className='photoOfOrder' key={postdata.img} src={postdata.img} wrapped ui={false} />
);
return (
<Card>
<div className="rating">
<span>☆</span><span>☆</span><span>☆</span><span>☆</span><span>☆</span>
</div>
<div>
{Photo}
</div>
<Card.Content>
<Card.Header
className='restaurantName'>{props.tileData.restaurantName}
</Card.Header>
<Card.Meta>
<span className='dateOfVisit'><b>Date Visited: </b> {props.tileData.dateOfVisit}</span>
</Card.Meta>
<Card.Meta>
<span className='restaurantType'><b>Type of Food: </b>{props.tileData.restaurantType}</span>
</Card.Meta>
<Card.Meta>
<span className='waitTime'><b>Wait Time: </b>{props.tileData.waitTime} minutes</span>
</Card.Meta>
<Card.Meta>
<span className='menuItem'><b>Item Ordered: </b>{props.tileData.menuItem}</span>
</Card.Meta>
<Card.Meta>
<span className='price'><b>Price: $</b>{props.tileData.price}</span>
</Card.Meta>
<Card.Meta>
<span className='foodRating'><b>Food rating: </b>{props.tileData.foodRating} Stars</span>
</Card.Meta>
<Card.Meta>
<span className='comments'><b>Comments: </b>{props.tileData.comments}</span>
</Card.Meta>
</Card.Content>
<Link to={`/edit/${props.tileData.id}`}>
<button className='edit-btn btn btn-bubble'>
Edit
</button></Link>
<button className='delete-btn btn2 btn-bubble2'
onClick={() => deleteReview(props.tileData)}>
Delete
</button>
</Card >
)
}
export default UserCard;```
Your problem is this,
const Photo = ({postsdata}) => (
<div>
{postsdata.map(postdata => (
<Image className='photoOfOrder' key={postdata.img} src={postdata.img} wrapped ui={false} />
))}
</div>
)
We never write functions inside of return, you just need to do this,
<div>
{postsdata.map(postdata => (
<Image className='photoOfOrder' key={postdata.id} src={postdata.img} wrapped ui={false} />
))}
</div>
Note: You have provided key={postdata.img}, when you have id then you should provide id as key which is more useful.
Update
To match any image randomly you can do this,
{postsdata.filter(postdata => postdata.id === props.index).map(data=> <Image className='photoOfOrder' key={data.id} src={data.img} wrapped ui={false} />)}
You need to pass index from parent component as,
<UserCard className='onecard' tileData={oneRest} setReviews={this.props.setReviews} index={Math.floor(Math.random()*15)+1} />
Here Math.floor(Math.random()*15)+1 will give you random number between 1 to 15.

Categories