read an array of objects in array of object - javascript

I have a problem to map an array of objects in an array of objects...
this is my array in back
const demoCompletedData = [
{
id: 1,
marketId: "1111-1111-1111-1111",
title: "Autonomous car",
picture: "https://th?id=OIP.fdvfdvfdvfdvfd&pid=Api",
language: "English",
flag: "🇬🇧",
completed: true,
date: "22/01/2019 10:30",
rate: 9.1,
categories: {
de: 1,
sp: 2,
uk: 0,
fr: 1,
us: 4,
},
},
module.exports = demoCompletedData;
And my code to read this in front :
fetchDemo
fetchDemo() {
this.props.demoFetchRequest();
const { marketId } = this.props.match.params;
axios.get(`/api/v1/passport-authenticate/market/${marketId}`)
.then((res) => {
return res.data;
})
.then(demo => this.props.demoFetchSuccess(demo))
.catch(error => this.props.demoFetchError(error));
}
and my return
and my return
and my return
and my return
const { demo } = this.props;
and my render
and my render
and my render
and my render
<p>
Categories :
{
Object.values(`${demo.categories}`).map((category) => {
return (
<ul>
<li>
{category.toString()}
</li>
</ul>
);
})}
</p>
How to solve this issue?
EDIT:
Thanks for your help. I want to read 'categories' and map it to show value of 'de', 'fr','us, 'uk' ... but I'm completely lost !
{
Object.keys(demo).filter((x) => { return x === 'categories'; }).map((category) => {
return (
<ul>
<li>
{category.de}
</li>
</ul>
);
})}
something like that :
{category.de > 0 ? `de : ${category.de}` : ''}
{category.us > 0 ? `us : ${category.us}` : '' }

Your category is object and you are trying to convert it to string. Try below code.
If you want key then
<li>
{Object.keys(category)[0]}
</li>
If you want value then
<li>
{Object.values(category)[0]}
</li>

Related

How can I create an unordered list in react based on array of objects?

I have an array of objects whose schema is something like this.
[
{ text: 'Contents', level: 2 },
{ text: 'h2 Heading', level: 2 },
{ text: 'h3 Heading', level: 3 },
{ text: 'h4 Heading', level: 4 },
{ text: 'Heading', level: 2 },
]
I want to create an unordered list based on the levels of each object.
So, for eg. the above array should be displayed as:
<ul>
<li>Contents</li>
<li>
h2 Heading
<ul>
<li>
h3 Heading
<ul>
<li>h4 Heading</li>
</ul>
</li>
</ul>
</li>
<li>Heading</li>
</ul>
I can check for the next object if it has the same level as the previous one. And handle the queries accordingly, but is there a better solution? Or any solution that works properly.
Edit #1: Just now, I found a solution that was asked here around 13 years ago. I can style the elements giving it a perception of a nested list. Link: Produce heading hierarchy as ordered list
Still, if there is a better solution, please do reply.
This is a possible solution. You can check this link for a reactive online code editor.
const objects = [
{ text: "Contents", level: 2 },
{ text: "h2 Heading", level: 2 },
{ text: "h3 Heading", level: 3 },
{ text: "h4 Heading", level: 4 },
{ text: "Heading", level: 2 }
];
const getDisplayableObjects = () => {
const arr = [];
let targetArr;
for (const obj of objects) {
const { text, level } = obj;
switch (level) {
case 2:
arr.push({ text, children: [] });
break;
case 3:
targetArr = arr[arr.length - 1].children;
targetArr.push({ text, children: [] });
break;
case 4:
targetArr = arr[arr.length - 1].children;
targetArr = targetArr[targetArr.length - 1].children;
targetArr.push({ text, children: [] });
break;
default:
break;
}
}
return arr;
};
const App = () => {
return (
<>
{getDisplayableObjects().map(({ text, children }) => (
<ul>
<li>
{text}
{children.map(({ text, children }) => (
<ul>
<li>{text}</li>
{children.map(({ text, children }) => (
<ul>
<li>{text}</li>
</ul>
))}
</ul>
))}
</li>
</ul>
))}
</>
);
};
export default App;
Result:

how to map an array of objects that has values of array of objects

I have a list of comments that I fetch from my API looking like this. A comment has likes and dislikes alongside the user who posted the like or dislike.
const comments = [
{
id: 1,
comment: "nice",
author: "jenny",
likes: [
{
id: 1,
user: "alice"
},
{
id: 2,
user: "bob"
}
],
dislikes: [
{
id: 3,
user: "sam"
}
]
},
{
id: 2,
comment: "good job",
author: "alice",
likes: [
{
id: 2,
user: "bob"
}
],
dislikes: [
{
id: 3,
user: "sam"
}
]
}
]
Lets say Alice is logged in.
Now the map to display the comments works fine, but I want to do "nested map" which loops through the likes and dislikes array of objects within the same object array and see if the user of a like or dislike matches who is logged in to display a confirmation.
My current code:
const signedInUser = "alice";
return(
Object.keys(comments).map((x, index) => {
const com = comments[x];
<div className="comment" key={index}>
<p>{com.author}</p>
<p>{com.comment}</p>
{com.likes.map((x) => {
{
x.user === signedInUser ? (
<p>You liked this</p>
) : (
<button>Like</button>
);
}
})}
</div>;
})
);
I am doing this with react, since I am trying to
You are suppose to use some to get a boolean response if there exist a like by the same user.
map return response for every object in the like array.
return(
Object.keys(comments).map((x, index) => {
const com = comments[x];
<div className="comment" key={index}>
<p>{com.author}</p>
<p>{com.comment}</p>
{com.likes.some((x) => x.user === signedInUser)?
(
<p>You liked this</p>
) : (
<button>Like</button>
);
}
</div>;
})
);
const renderLikeOrDislikeButton = (arr, text1, ) =>{
if(arr.some((x) => x.user === signedInUser)){
return <p>You {text1} this</p>
}
return <button>{text2}</button>
}
return(
{
Object.keys(comments).map((x, index) => {
const com = comments[x];
return(
<div className="comment" key={index}>
<p>{com.author}</p>
<p>{com.comment}</p>
{renderLikeOrDislikeButton(com.likes, "liked", "Like")}
{renderLikeOrDislikeButton(com.likes, "disliked", "Dislike)}
</div>
)
});

Mapping an array of each object in array in React

I've got a data.json file with an array of group objects, and each group object contains products array, like:
[
{
"groupId": int
"familyId": int,
"products": array (lenght of 10-50)
}
{
"groupId": int
"familyId": int,
"products": array (lenght of 10-50)
}, and so on...
]
I would like to map them like:
<ul> GroupId
<li>Product 1</li>
<li>Product 2</li>
<ul/>
<ul>
GroupId
<li>Product 1</li>
<li>Product 2</li>
</ul>
etc.
I've tried to use foreach function and then map every array but it doesn't work.
import data from '../data.json';
let productsList = [];
{data.forEach((el) => {productsList.push(el.products)})}
{productsList.forEach((array) => {
array.map((el) => {
return (
<ul>
<li>{el.name}</li>
</ul>
)
})
})}
I recommend you solve this with simple react components, it will make your code more readable.
I created a simple example to solve your issue
export default function App() {
const data = [
{
groupId: 1,
familyId: 1,
products: [
{ id: 1, name: "product 1", price: 10 },
{ id: 2, name: "product 2", price: 20 }
]
},
{
groupId: 2,
familyId: 2,
products: [{ id: 3, name: "product 3", price: 30 }]
}
];
return (
<div className="App">
{data.map((group) => (
<ProductGroup group={group} />
))}
</div>
);
}
ProductGroup Component
const ProductGroup = ({ group }) => {
return (
<>
<ul>{group.groupId}</ul>
{group.products.map((product) => (
<ProductItem product={product} />
))}
</>
);
};
ProductItem Component
const ProductItem = ({ product }) => {
return (
<li>
<span>{product.name}</span>
<span style={{ marginLeft: "10px" }}>{product.price}$</span>
</li>
);
};
Try this one
const listItems = () => (
<>
{array.map((group) => (
<ul key={group.groupId}>
{group.groupId}
{group.products.map((productList, index) => (
<li key={index}>{productList}</li>
))}
</ul>
))}
</>
);

Data object with array of different groups, trying to display ordered by group type using .map() and pushing to new array nothing is rendering

I have a React Component I'm building out that accepts a data object as props.
This data object holds an array of groups each with it's own group type.
What I'm trying to do is map over each group in the array and display it's contents as it's own section, but I also want to ensure that all of the objects with the type grid display together, followed by any sections with a list type no matter what position they are in the array.
So even if the array holds the values like:
[{Grid}, {List}, {Grid}, {List}, {Grid}]
It will display like this:
Group #1 (Grid)
Contents
Group #2 (Grid)
Contents
Group #3 (Grid)
Contents
Group #4 (List)
Contents
Group #5 (List)
Contents
The problem I'm having is that I wrote two separate components to handle the styling of each type and then passed them into a function that creates a new array from the original to then render, and nothing is displaying. I'm not getting any error messages or anything in the console so I'm completely stumped as to where I'm going wrong.
Here are my components, the data structure and a Codesandbox:
// Component File
import "./styles.css";
import data from "./resourceMock";
import FileIcon from "./FileIcon";
const GridView = (group) => {
const { groupName, items } = group;
return (
<>
<h2>{groupName}</h2>
<ul
style={{
display: "inline-flex",
flexWrap: "wrap",
listStyleType: "none"
}}
>
{items.map((item) => {
return (
<li style={{ height: "40vh", flexGrow: 1 }}>
<img src={item.img} style={{ height: "150px", width: "150px" }} />
<h4>{item.name}</h4>
<h5>{item.subtitle}</h5>
</li>
);
})}
</ul>
</>
);
};
const ListView = (group) => {
const { groupName, items } = group;
return (
<>
<h2>{groupName}</h2>
<ul style={{ listStyleType: "none" }}>
{items.map((item) => {
return (
<li>
<FileIcon />
{item.title}
</li>
);
})}
</ul>
</>
);
};
function renderList(group) {
const lists = [];
if (!group) return null;
data.map((group) => {
switch (group.groupType) {
case "grid":
return lists.push((group) => {
<GridView group={group} />;
});
case "list":
return lists.push((group) => {
<ListView group={group} />;
});
default:
return lists.push((group) => {
<ListView group={group} />;
});
}
});
return lists;
}
export default function App() {
return <div className="App">{data.map((group) => renderList(group))}</div>;
}
Data Structure:
export default [
{
groupName: "Marvel Characters",
groupType: "grid",
items: [
{
name: "Iron Man",
subtitle: "Inventor Tony Stark",
img:
"https://www.denofgeek.com/wp-content/uploads/2019/02/mcu-1-iron-man.jpg?resize=768%2C432"
},
{
name: "Incredible Hulk",
subtitle: "Bruce Banner",
img:
"https://lh3.googleusercontent.com/proxy/-jHnFcGLqlxjdOl9Mf99UPBk4XJKcQ1Hsv7lPYEs8Vai874sW0l5TUwn3acriwGpE36aUDPpZHPFzccRUt7b7POGOWCFIbgYomTO9bDCXF0eovxFGdr_D3P-0wfLnkUMOOJDG09MgAzqSCbiDq-A"
}
]
},
{
groupName: "Magic Cards",
groupType: "list",
items: [
{
title: "Kamahl, Fist Of Krosa",
link:
"https://gatherer.wizards.com/pages/card/Details.aspx?multiverseid=220490"
},
{
title: "Seedborn Muse",
link:
"https://gatherer.wizards.com/pages/card/Details.aspx?multiverseid=446180"
}
]
},
{
groupName: "DC Characters",
groupType: "grid",
items: [
{
name: "Batman",
subtitle: "Bruce Wayne",
img:
"https://static.wikia.nocookie.net/marvel_dc/images/a/a6/Batman_Vol_2_2_Variant_Textless.jpg/revision/latest/top-crop/width/360/height/450?cb=20120228075313"
},
{
name: "Martian Manhunter",
subtitle: "J'onn J'onzz",
img:
"https://cdn.flickeringmyth.com/wp-content/uploads/2021/03/Martian-Manhunter-600x338.png"
}
]
},
{
groupName: "Kaiju and Mechs",
groupType: "grid",
items: [
{
name: "Godzilla",
img:
"https://www.denofgeek.com/wp-content/uploads/2019/05/godzillakingofmonsters-2.jpg?resize=768%2C432"
},
{
name: "Hunter Vertigo",
img: "https://i.ytimg.com/vi/7F-iZYAqSbw/maxresdefault.jpg"
}
]
},
{
groupName: "Comic Books",
groupType: "list",
items: [
{
title: "Descender",
link: "https://imagecomics.com/comics/series/descender"
},
{
title: "East of West",
link: "https://imagecomics.com/comics/series/east-of-west"
},
{
title: "Letter 44",
link: "https://onipress.com/collections/letter-44"
}
]
}
];
I have fixed the issues.
Sandbox: https://codesandbox.io/s/affectionate-sinoussi-5suro
You are already looping over data inside renderList, so we can directly have <div className="App">{renderList(data)}</div>;
To sort, we can use Array.sort()
data.sort((a, b) => a.groupType === b.groupType ? 0 : a.groupType > b.groupType ? 1 : -1);
Also, in switch case you need to push the component and not a function.
case "grid":
lists.push(<GridView group={group} />);
break;
Need to use destructuring here const ListView = ({ group }) => {}
Finally add key to your lists. I have added using the item name, but you need to change per your requirement.

Sort a filtered array with a higher order function in computed properties [vue.js]

I want to switch between different sorting methods to sort an array by numbers, dates and titles and so on.
I want to store all sort methods in the created hook as higher order functions:
created () {
this.sortings = [
{
asc: (img1, img2) => img2[this.sortBy] - img1[this.sortBy],
desc: (img1, img2) => img1[this.sortBy] - img2[this.sortBy],
compare: (a, b) => a.ratio - b.ratio
}
]
}
my computed property looks like this:
computed: {
resultsFiltered () {
return this.imgData.filter(...).sort(this.sortings[this.sortMethod])
}
}
},
My goal is to switch the sorting by changing the sortMethod in the Data object:
data () {
return {
sortMethod: "compare" // or "asc", "desc",
sortBy: "ratio" // or "date", "title", "filesize", ...
}
}
How can I reach the higher order function in 'these.sortings' to sort my computed property?
Also, I don't know how to pass the parameters to the sorting functions :/
I hope you can help me, thanks!
In order to get a reactivity working you should place this.sortings in the data section.
Also you need to correct this.sortings if you wish it to work like a dictionary:
this.sortings = {
asc: (img1, img2) => img2[this.sortBy] - img1[this.sortBy],
desc: (img1, img2) => img1[this.sortBy] - img2[this.sortBy],
compare: (a, b) => a.ratio - b.ratio
}
Parameters to a comparator function is passed by the array's sort method.
Array.prototype.customSort = function (key, order='asc') {
let arrayOfObject = [...this]
let compare = (a,b) => {
if (a[key] < b[key]) {
return order === "asc" ? -1 : 1;
}
if (a[key] > b[key]) {
return order === "asc" ? 1 : -1;
}
return 0
}
return arrayOfObject.sort(compare)
}
new Vue({
el: '#app',
data: {
filteredArray: [
{ serialNo: 1, date: '1994-12-20', title: 'big title' },
{ serialNo: 2, date: '1994-12-22', title: 'small title' },
{ serialNo: 3, date: '1993-12-20', title: 'large title' },
{ serialNo: 4, date: '1992-12-20', title: 'mid title' },
{ serialNo: 5, date: '1991-12-20', title: 'great title' },
{ serialNo: 6, date: '1994-10-20', title: 'awesome title' }
],
currentKey: 'serialNo',
currentOrder: 'asc'
},
computed: {
getSortedFilteredArray () {
return this.filteredArray.customSort(this.currentKey, this.currentOrder)
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<!-- CHOOSE KEY TO SORT -->
<span>Select key: </span>
<button #click="currentKey = 'serialNo'">serialNo</button> |
<button #click="currentKey = 'date'">date</button> |
<button #click="currentKey = 'title'">title</button>
<br/>
<!-- CHOOSE ORDER TO SORT -->
<span>Select order: </span>
<button #click="currentOrder = 'asc'">asc</button> |
<button #click="currentOrder = 'desc'">desc</button>
<br/>
<!-- SELECTED SORT / ORDER -->
<span>Current key : {{ currentKey }}</span> |
<span>Current order : {{ currentOrder }}</span>
<!-- SORTED RESULT -->
<ul>
<li
v-for="(obj, i) in getSortedFilteredArray"
:key="i"
>
{{ obj }}
</li>
</ul>
</div>

Categories

Resources