filter array in props - arrays

i keep having a problem with filtering an array of objects in props in a nextjs page. i m using below json and coding.
[
{
"id": "1",
"name": "name1",
"category": ["food"]
},
{
"id": "2",
"name": "name2",
"category": ["food", "beverages"]
}]
import React from "react";
const test2 = ({ prods }) => {
return (
<div>
<div>
{prods
.filter((product) => product.category.includes("eve"))
.map((filterarray) => (
<li>
{filterarray.id}
{filterarray.name}
{filterarray.category}
</li>
))}
</div>
</div>
);
};
export async function getStaticProps() {
const prods = (await import("./product.json")).default;
return {
props: {
prods,
},
};
}
export default test2;
listing the full array works. (data comes as 1 string eg 'foodbeverage' but that should still be ok i think)
Filtering on id works fine. But when i try to use include it no longer displays any result.
if anyone could point me to what i m doing wrong. or if i better follow a different approach, any help would be much appreciated.

You need to replace include with some on the category array:
let prods = [
{
id: "1",
name: "name1",
category: ["food"]
},
{
id: "2",
name: "name2",
category: ["food", "beverages"]
}
];
let result = prods.filter((product) =>
product.category.some((pro) => pro.includes("eve"))
);
console.log(result);

Array#includes() does not do partial matches. You need to use String#includes() on each element in the array.
You could do this by using Array#some() in the filter.
prods.filter((product) => product.category.some(cat=>cat.includes("eve")))

Related

How to create an array from a Obj in another array? JS React

I want to build a self updating filter with checkboxes.
My Data:
const Shooting= [
{
name: "John & Johna ",
tag: ["wedding", "couple"],
img: [ src1 , src2, ...] //irrelevant
},
{
name: "Mario & Marie",
tag: ["couple", "NSFW"],
img: [ src1 , src2, ...] //irrelevant
},
];
export default Shooting;
how my output should look like that:
Filter:
[]wedding
[]couple
[]NSFW
// [] are checkboxes, "couple" is a duplicate in the array
My code idea:
Get all tags into a new array
Build function to remove duplicates from new array
list the filtered array with map-function -> Obj.map((tag))=>{...}
My question:
How can I get all tags in a new list?
You can try with [...new Set(Shooting.map(({ tag }) => tag).flat(1))],
-> Shooting.map(({tag}) => tag) will give back the tags in array.
-> Then we can use array.flat() to concatenate the tags.
-> Then to remove duplicate, we use ...new Set(...) .
const App = () => {
const Shooting = [
{
name: "John & Johna ",
tag: ["wedding", "couple"],
img: ["src1", "src2"]
},
{
name: "Mario & Marie",
tag: ["couple", "NSFW"],
img: ["src1", "src2"]
}
];
const result = [...new Set(Shooting.map(({ tag }) => tag).flat(1))];
return <div>
<h2> Filter: </h2>
<ul>
{
result.map((list, i) => <div key={i}><input type="checkbox" /> {list} </div> )
}
</ul>
</div>
}
// Render it
ReactDOM.createRoot(
document.getElementById("root")
).render(
<App />
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
Create reduce function with set
const Shooting= [
{
name: "John & Johna ",
tag: ["wedding", "couple"],
},
{
name: "Mario & Marie",
tag: ["couple", "NSFW"],
},
];
const result = Shooting.reduce((acc, item) => {
return [ ...new Set([...acc, ...item.tag]) ]
}, [])
console.log(result)
You can use a reducer to get all unique tags
const array = [
{
name: "name1",
tag: ["tag1", "tag2"],
},
{
name: "name2",
tag: ["tag2", "tag3"],
},
];
const tags = array.reduce((acc, item) => {
item.tag.forEach((tag) => {
if (!acc.includes(tag)) {
acc.push(tag);
}
});
return acc;
}, []);
Then with your tags you can do whatever you want. Good luck!

Fetching , rendering and sorting data in Reactjs

How can i fetch data from a json file and render them in an ascending order? For example let´s say i have this json file
[{
"id": 0,
"name": "Vernon Dunham",
"company": "Qualcore",
"email": "vernon.dunham#qualcore.com"
}, {
"id": 1,
"name": "Dori Neal",
"company": "Sunopia",
"email": "dori.neal#sunopia.com"
}, {
"id": 2,
"name": "Rico Muldoon",
"company": "Airconix",
"email": "rico.muldoon#airconix.com"
}
and i want to render the data with only Id and name in ascending order.
I tried coding it in different ways but since i am still a beginner i can´t really figure it out. Thank you so much
You can use .map and .sort:
const data = [{
"id": 0,
"name": "Vernon Dunham",
"company": "Qualcore",
"email": "vernon.dunham#qualcore.com"
}, {
"id": 1,
"name": "Dori Neal",
"company": "Sunopia",
"email": "dori.neal#sunopia.com"
}, {
"id": 2,
"name": "Rico Muldoon",
"company": "Airconix",
"email": "rico.muldoon#airconix.com"
}]
const sorted = data.map(d => ({id: d.id, name: d.name})).sort((el1, el2) => el1.id - el2.id)
console.log(sorted)
Once you set the new sorted and mapped array to a state variable, you can map over it to render.
Example
//Functional Component:
const Example = ({data}) => {
const [sortedData, setSortedData] = useState([])
useEffect(() => {
if(data) setSortedData(data
.map(d => ({id: d.id, name: d.name}))
.sort((el1, el2) => el1.id - el2.id)))
}, [data])
return(
sortedData?.map(element => <div key={element.id}> {element.name} </div>)
)
}
You can short your array data using the .sort method.
App.js
import React, { useState, useEffect } from "react";
import Data from "./data.json";
function App() {
const [data, setData] = useState();
const sortDataByField = (array, field) => {
return array.sort((a, b) =>
a[field].toString().localeCompare(b[field].toString())
);
};
useEffect(() => {
const sortData = sortDataByField(Data, "name");
setData(sortData);
}, []);
return (
<div className="App">
{data?.map((item) => (
<div key={item.id}>{item.name}</div>
))}
</div>
);
}
export default App;
data.json
[{
"id": 0,
"name": "Vernon Dunham",
"company": "Qualcore",
"email": "vernon.dunham#qualcore.com"
}, {
"id": 1,
"name": "Dori Neal",
"company": "Sunopia",
"email": "dori.neal#sunopia.com"
}, {
"id": 2,
"name": "Rico Muldoon",
"company": "Airconix",
"email": "rico.muldoon#airconix.com"
}]
Import and set up a useState hook
import React, {usesState} from 'react'
const [companies, setCompanies] = useState([])
fetch the data
const data = fetch('/api/v1/companies', {method: 'GET'})
sort first to order, then map to only get id and name
const sorted = data.sort((a, b)=>{return a.name > b.name ? 1 : -1})
.map(({id, name}) => {return {id, name}})
/* this return only id and name sorted by name
*
* if you wanna sort by id, do this:
* .sort((a, b) => a.id - b.id)
*/
When you done sorting and mapping, store it to that useState hook so that you can render it:
setCompanies(sorted)
Then render it, also prevent errors by checking if you state has data before rendering:
companies &&
companies.map(({id, name}) => <h1 key={id}>{name}</h1>)
// or
companies
? companies.map(({id, name}) => <h1 key={id}>{name}</h1>)
: <p>No data</p>
All code
import React, {usesState, useEffect} from 'react'
export default App = () =>{
const [companies, setCompanies] = useState([])
useEffect(()=>{
fetchData()
}, [])
const fetchData = async () => {
try{
const data = fetch('/api/v1/companies', {method: 'GET'})
if(data){
const sorted = data.sort((a, b)=>{return a.name > b.name ? 1 : -1})
.map(({id, name}) => {return {id, name}})
setCompanies(sorted)
}
else{
console.log('No data')
}
}
catch (err){
console.log(err)
}
}
return(
<div>
companies &&
companies.map(({id, name}) => <h1 key={id}>{name}</h1>)
</div>
)
}

Nested array with React and Firestore - How to display?

I have a nested array within the individual items in a collection.
{
"id": "RpFRcKLIgELlBLgIOJM4",
"Category": "",
"Method": "",
"User": "rWFZhAKk9eOSIIFoP0DqqvrC6WJ3",
"Foods": [
{
"Weight": 1.065,
"label": "Milk - Long Life (1 Litre) (1.065)",
"value": "Milk-LongLife(1Litre)"
},
{
"label": "Blueberries (0.125)",
"value": "Blueberries",
"Weight": 0.125
}
],
"Name": "456",
"Serves": ""
}
{
"id": "WQ6KBLevFsCdV73j4KU4",
"Category": "",
"Name": "123",
"Foods": [
{
"value": "Wine-White",
"label": "Wine - White"
},
{
"value": "Milk-LongLife(1Litre)",
"label": "Milk - Long Life (1 Litre)"
}
],
"Serves": "",
"User": "rWFZhAKk9eOSIIFoP0DqqvrC6WJ3",
"Method": ""
}
const useItemsMeals = () => {
const user = firebase.auth().currentUser;
const user1 = user.uid;
const [items, setItems] = useState([]); //useState() hook, sets initial state to an empty array
useEffect(() => {
const unsubscribe = firebase
.firestore()
.collection("meals")
.where("User", "==", user1)
.orderBy("Category", "asc")
.onSnapshot(snapshot => {
const listItemsMeals = snapshot.docs.map(doc => ({
id: doc.id,
...doc.data()
}));
setItems(listItemsMeals);
console.log(listItemsMeals);
});
return () => unsubscribe();
}, []);
return items;
};
I am having a tough time trying to display items from the 'Foods' array, am currently using for my return:
const listItemMeals = useItemsMeals();
{listItemMeals.map(item => (
<TableRow hover key={item.id} id={item.id}>
<TableCell>{item.Category}</TableCell>
<TableCell>{item.Name}</TableCell>
<TableCell>{item.Foods}</TableCell>
When doing this it tells me:
Error: Objects are not valid as a React child (found: object with keys {label, value}). If you meant to render a collection of children, use an array instead.
I think I need to map this nested array again somehow - but for the life of me - cannot figure it out!
You're almost there.
Your useItemsMeals functions loads the data from Firestore, and sets it correctly into the items variable in the state to render it. But then you use const listItemMeals = useItemsMeals() in your rendering code, which messes things up.
You should not try to return any value from useItemsMeals, and instead solely rely on the items variable from the state to pass the information between the database and the rendered.
So:
// return items; 👈 remove this
---
// const listItemMeals = useItemsMeals(); 👈 remove this
---
{items.map(item => ( // 👈 read items from the state instead
You need to loop over the Foods array again. Like this
const listItemMeals = useItemsMeals();
{listItemMeals.map(item => (
<TableRow hover key={item.id} id={item.id}>
<TableCell>{item.Category}</TableCell>
<TableCell>{item.Name}</TableCell>
{
item.Foods.map(food=>(
<div> //this can div or a new row tag
<TableCell>{food.weight}</TableCell>
<TableCell>{food.label}</TableCell>
<TableCell>{food.value}</TableCell>
</div>))
}

How can I acces a nested object from my API

I made an API with spring-boot that is able to create Cook objects with Recipes objects in it. The idea is that one cook has a relationship with (multiple) recipe(s). When I perform a get request to my server, I am able to show the entire (Cook) object with nested (Recipe) object(s). I am also able to render Cook object properties to the browser, e.g name, age etc. However, I am not able to render Recipe properties to the browser from within the Cook object. It always gives me an undefined.
My code for the API request that shows the name from a cook correctly :
const [posts, setPosts] = useState([]);
useEffect(()=> {
axios.get(" http://localhost:9090/api/cooks")
.then(response => {
console.log(response.data) //response.data.recipe.x doesn't seem to work.
setPosts(response.data);
})
.catch(error => {
console.log(error)
})
},[])
return (
<div>
{posts.map(post => <li key={post.id}>{post.name}</li>)}; //post.recipe.x also doesn't work
</div>
)
}
const Index = () => {
return (
<div>
<Alt />
</div>
)
}
The raw JSON data from the server looks like this:
{
"id": 1,
"name": "bart",
"surName": "Janssen",
"gender": "male",
"age": 3,
"recipes": [
{
"id": 1,
"recipeName": "Hamburger",
"portion": 1,
"meat": "Ground meat",
"vegetable": "Tomato, Pickles, other greens",
"other": "salt, pepper, mustard, ketchup",
"instructions": "bla bla"
},
{
"id": 2,
"recipeName": "tomato soup",
"portion": 2,
"meat": null,
"vegetable": "tomato",
"other": "salt, stock",
"instructions": "bla bla"
}
]
}
]
However, I really need to access the Recipe properties too.
I tried accessing recipes through response.data[0], response.data[0][0], response.data[0][1], response.data[[0][0]] However, they all seem to give me an undefined back or an error.
I also tried to use JSON.Stringify(response.data), but this didn't give me any successes too.
I really could use some help. Thanks in advance :)
try to use useEffect with async/await
useEffect(async () => {
const result = await axios(
'http://localhost:9090/api/cooks',
);
setData(result.data.recipes);
});
and another moment, you initialize
const [posts, setPosts] = useState([]);
as an array - useState([ ]), but trying to write a data as object -
{
"id": 1,
"name": "bart",
"surName": "Janssen",
....
}
that's why you need to straight extract recipes
setData(result.data.recipes);

How to access data returned from props

I new to nextjs and react. I am using the nextjs to fetch data from api and display it in view. this is my code.
const Index = props => (
<Layout>
<h1>Events</h1>
<ul>
{props.eventList.map(({ venue }) => (
<li key={venue.name}>
<a>{venue.name}</a>
</li>
))}
</ul>
</Layout>
);
Index.getInitialProps = async function() {
const res = await fetch("api link here");
let data = await res.json();
console.log(`Show data fetched. Count: ${data.events.length}`);
return {
eventList: data.events
};
};
Now my api return data like this
[
{
"id": 4303920,
"name": "Test Event",
"venue": {
"id": 1610,
"name": "Eiffel Tower Viewing Deck at Paris Las Vegas",
}
},
{
"id": 4323,
"name": "Test Event 2",
"venue": {
"id": 1610,
"name": "Eiffel Tower Viewing Deck at Paris Las Vegas",
}
}
]
I am able to access the venue details by props.eventList.map function but i am not able to access the id and name.
In your map instead of ({venue}) => just do (item) => your issue is you are getting each element and only extracting venue from it instead of the entire element. Once you have item you can say item.id, item.venue etc.
You should not put {venue} inside your map function but pass the event like this (event) then you will have even.name and event.is and you will have event.venue.id and event.venue.name

Resources