React - Loop through multiple nested arrays json object response then update State - javascript

I have some data that has the following shape. The schedule data also has other identifying information attached to it, being schedules.included which is an array of arrays. I want to loop through each included array and find it by type element. I'm not entirely sure how to get each included[] by type then update state with data from each array, respectively. Is forEach the correct approach?
const schedules = {
data: [
{
id: "2147483610",
type: "Schedule"
}
],
included: [
{
id: "21468486",
type: "Query",
name: "Query1"
},
{
id: "43573457345",
type: "DataSource",
name: "DataSource1"
}
]
};
I then want to update state with whatever data I need.
getData = () => {
axios({
method: "get",
url: `/endpoint/with/this/data`
})
.then(response => {
console.log(response);
var obj = schedules.included[i].type;
obj.forEach(function(type) {
alert(type.name);
});
this.setState({
schedules: schedules.data,
//update with name from type Query
});
})
.catch(error => console.log(error.response));
};

If you want to find the name of the element from the included array which has type = Query, and there is only one such element:
var query = schedules.included.find(el => el.type == "Query");
console.log(query.name); // output Query1
If there is more than one query element you could use filter to get all query elements, then loop thru them doing stuff with each one.
var queries = schedules.included.filter(el => el.type == "Query");
queries.forEach(q => console.log(q.name));

If there is only one element with the type you are looking for then you can use find or if there is more use filter.
const schedules = {
data: [
{
id: "2147483610",
type: "Schedule"
}
],
included: [
{
id: "21468486",
type: "Query",
name: "Query1"
},
{
id: "43573457345",
type: "DataSource",
name: "DataSource1"
}
]
};
const typeMatched = schedules.included.find( included => included.type === "Query");
console.log(': ', typeMatched);
const schedulesObj = {
data: [
{
id: "2147483610",
type: "Schedule"
}
],
included: [
{
id: "21468486",
type: "Query",
name: "Query1"
},
{
id: "43573457345",
type: "DataSource",
name: "DataSource1"
},
{
id: "21468482",
type: "Query",
name: "Query2"
},
{
id: "21468484",
type: "Query",
name: "Query3"
},
]
};
const typeMatchedArray = schedulesObj.included.filter( included => included.type === "Query");
console.log('Query Type List: ', typeMatchedArray)

Related

Node Js how to fetch data from database in an hierarchical way

I'm writing a back code using NodeJs to fetch some data from backend, I want dataBase data to be like this
like this:
data = [{
name: "Admin",
id: '1',
children: [
{ name: "Admin", id: "1" },
{ name: "groupe1", id: "2" },
{
name: "groupe2", id: "1455", children: [
{ name: "groupe2", id: "1455" },
{ name: "gro", id: "5444" },
{ name: "hhrr", id: "45" }
]
}
]
}]
the idea is simple we have a list of group each group has a parent I want to display all the groups list in an hierarchical way the top one of the tree is done
Some groups are parents and groups in the same time and some others are only groups if the group is not parent we add an object with its name and ID in the array of children of his parent
if this groups is a parent that's mean it has children we add an object with its ID and name in the array of children of his parents, and we add property children for the object which is array named children with for the first time an object with the name and the id of the group etc...
i tryed to do this but it did not work
const getParentsByType = async ({ name, _id }) => {
let parentResult = [
{
id: _id,
name: name,
children: [
{
id: _id,
name: name,
},
],
},
];
parentResult= await findParent(_id, parentResult[0].children, 0);
return parentResult;
};
const findParent = async (parentId, parentResult, itemPos) => {
let children = await Models.GroupModel.find({ parent: parentId, status: true }).select('name _id');
for (let i = 0; i < children.length; i++) {
let childrenList = await Models.GroupModel.find({ parent: children[i]._id, status: true }).select('name _id');
if (childrenList.length != 0) {
parentResult.push(buildParentWithChild(children[i]._id, children[i].name));
findParent(children[i]._id,parentResult.children[i],itemPos++)
} else {
parentResult.push(buildParent(children[i]._id, children[i].name));
}
}
return parentResult
};
and this the model of the data base
const Group = mongoose.Schema({
name: {
type: String,
required: true,
},
status: {
type: Boolean,
required: true,
},
parent: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Group',
},
});
i had two days trying to resolve tis but with no result
i need some helps and Thank you
Try parsing your returned data. It validates your data as objects i dont see any problem with your function regardless i still have no idea what format your a trying to build.
let children = JSON.parse(JSON.stringify(await Models.GroupModel.find({ parent: parentId, status: true }).select('name _id')));
let childrenList = JSON.parse(JSON.stringify(await Models.GroupModel.find({ parent: children[i]._id, status: true }).select('name _id')));
If I understand you right, you want to convert the array returned by Models.GroupModel.find, and which looks like
var dbresult = [
{_id: "1", parent: null, name: "one"},
{_id: "2", parent: "1", name: "two"}
];
into a hierarchical structure. This can be done with a function that adds all children of a given parent p, including, recursively, their children. Like the following:
function children(p) {
var result = [];
for (r of dbresult) if (r.parent === p) {
var row = {_id: r._id, name: r.name};
var chld = children(r._id);
if (chld.length > 0) row.children = chld;
result.push(row);
}
return result;
}
console.log(JSON.stringify(children(null)));
Note that this approach requires only one database access (to fill the dbresult) and is therefore probably faster than your findParent function.

I think a better knowledge of javascript array methods will help me?

I'm trying to update an array of products in a custom mutation in keystone-next. I have got as far as the below, which works for the first product in my array. Obviously this only works if there is only 1 item in the array.
I know I need to map through the array in some way but I can't get my head round it.
const productIds = user.cart.map((cartItem) => cartItem.product.id);
console.log(productIds)
await context.lists.Product.updateMany({
// this is the bit that's wrong
data: [
{
id: productIds[0],
data: {
status: 'PENDING',
},
},
],
});
Yes, you need to map through your array of productIds
const productIds = user.cart.map((cartItem) => cartItem.product.id);
productIds.map(async (id) => {
await context.lists.Product.updateMany({
data: [
{
id,
data: {
status: 'PENDING',
},
},
],
});
})
But most efficiently you should handle the update in the first map without getting the array of productIds first. Like this
user.cart.map(async(cartItem) => {
await context.lists.Product.updateMany({
data: [
{
id: cartItem.product.id,
data: {
status: 'PENDING',
},
},
],
});
});
Something like this u mean?
const productIds = user.cart.map((cartItem) => cartItem.product.id);
console.log(productIds)
await context.lists.Product.updateMany({
data: productIds.map(productId => ({
id: productId,
data: {
status: 'PENDING',
},
}))
});

Filter an array containing a list of articles as Objects

I have an array containing 7 objects, all of the articles. I need to be able to show only the first 3 articles
const myArray = [
{
id: "article_1",
type: "articles"
},
{
id: "article_2",
type: "articles"
},
{
id: "article_3",
type: "articles"
},
{
id: "article_4",
type: "articles"
},
{
id: "article_5",
type: "articles"
},
{
id: "article_6",
type: "articles"
},
{
id: "article_7",
type: "articles"
}
]
const filteredArticles = myArray.filter(article => myArray.length > 3)
console.log(filteredArticles)
Unfortunately, it returns an empty array instead of an array with articles.
I know a solution could be to use if(myArray.length > 3) { //show only index 0, 1, 2, 3 } else { // blah blah}
But I am trying to use js .filter which should easily hide the number of articles over 3.
Try
myArray.filter((_,i) => i < 3)
const myArray = [
{
id: "article_1",
type: "articles"
},
{
id: "article_2",
type: "articles"
},
{
id: "article_3",
type: "articles"
},
{
id: "article_4",
type: "articles"
},
{
id: "article_5",
type: "articles"
},
{
id: "article_6",
type: "articles"
},
{
id: "article_7",
type: "articles"
}
]
const filteredArticles = myArray.filter((_,i) => i < 3);
console.log(filteredArticles);
The second argument of the callback passed to filter is the current index. So you can do something like:
const filteredArticles = myArray.filter((article, i) => {
return i < 3;
});
That would be truthy for only the first three elements, so you're filtered array would be the first three. Keep in mind that filter will still check the rest of the array, so there might be a more performant way of doing this.
EDIT: As some commenters have mentions, .slice would be a better way of doing this as you don't have to then iterate over the rest of the array as in the filter solution.

Typescript - get array that satisfy a condition

Is it possible to get an output array from the given that contains roles=1 without duplicate ?
Iam using angular 6 typescript. Is there any typescript array processing functions to do this operation
//Input Array
export const userMenus = [
{
name: 'Dashboard',
url: '/dashboards',
icon: 'icon-speedometer',
roles:'1,3,4'
},
{
name: 'Users',
url: '/Users',
icon: 'icon-bell',
roles:'1,2,3,4'
},
{
name: 'Article',
url: '/Users',
icon: 'icon-bell',
roles:'1,2,3,4',
children: [
{
name: 'Cards',
url: '/base/cards',
icon: 'icon-puzzle',
roles:'1,3,4',
},
{
name: 'Carousels',
url: '/base/carousels',
icon: 'icon-puzzle',
roles:'2,4',
},
{
name: 'Collapses',
url: '/base/collapses',
icon: 'icon-puzzle',
roles:'4'
}
]
}
]
--Need Output if role is 2.
removed items that not contain 2 in the role field
userMenus = [
{
name: 'Users',
url: '/Users',
icon: 'icon-bell',
roles:'1,2,3,4'
},
{
name: 'Article',
url: '/Users',
icon: 'icon-bell',
roles:'1,2,3,4',
children: [
{
name: 'Carousels',
url: '/base/carousels',
icon: 'icon-puzzle',
roles:'2,4',
},
]
}
You must filter your array and verify that you have 2 in your roles :
const filteredUserMenus = userMenus.filter((userMenu) => {
return userMenu.roles.find((role) => role === '2');
});
short syntax :
const filteredUserMenus = userMenus.filter((userMenu) =>
userMenu.roles.find((role) => role === '2'));
EDIT : your data structure is bad, roles shouldn't be a string but an array of role. Anyway, if you can't change it, here is a solution :
const filteredUserMenus = userMenus.filter((userMenu) => {
return userMenu.roles.split(',').find((role) => role === '2');
});
short syntax :
const filteredUserMenus = userMenus.filter((userMenu) =>
userMenu.roles.split(',').find((role) => role === '2'));

How to return an array of objects in GraphQL, possibly using the same endpoint as the one that returns a single object?

I am making a GraphQL API where I would be able to retrieve a car object by its id or retrieve all the cars when no parameter is provided.
Using the code below, I am successfully able to retrieve a single car object by supplying id as a parameter.
However, in the case where I would expect an array of objects i.e. when I supply no parameter at all, I get no result on GraphiQL.
schema.js
let cars = [
{ name: "Honda", id: "1" },
{ name: "Toyota", id: "2" },
{ name: "BMW", id: "3" }
];
const CarType = new GraphQLObjectType({
name: "Car",
fields: () => ({
id: { type: GraphQLString },
name: { type: GraphQLString }
})
});
const RootQuery = new GraphQLObjectType({
name: "RootQueryType",
fields: {
cars: {
type: CarType,
args: {
id: { type: GraphQLString }
},
resolve(parent, args) {
if (args.id) {
console.log(cars.find(car => car.id == args.id));
return cars.find(car => car.id == args.id);
}
console.log(cars);
//***Problem Here***
return cars;
}
}
}
});
Test queries and their respective results:
Query 1
{
cars(id:"1"){
name
}
}
Query 1 Response (Success)
{
"data": {
"cars": {
"name": "Honda"
}
}
}
Query 2
{
cars{
name
}
}
Query 2 Response (Fail)
{
"data": {
"cars": {
"name": null
}
}
}
Any help would be much appreciated.
A Car and a List of Cars are effectively two separate types. A field cannot resolve to a single Car object one time, and an array of Car object another.
Your query is returning null for the name because you told it the cars field would resolve to a single object, but it resolved to an array instead. As a result, it's looking for a property called name on the array object and since one doesn't exist, it's returning null.
You can handle this in a couple of different ways. To keep things to one query, you can use filter instead of find and change the type of your query to a List.
cars: {
type: new GraphQLList(CarType), // note the change here
args: {
id: {
type: GraphQLString
},
},
resolve: (parent, args) => {
if (args.id) {
return cars.filter(car => car.id === args.id);
}
return cars;
}
}
Alternatively, you could split this into two separate queries:
cars: {
type: new GraphQLList(CarType),
resolve: (parent, args) => cars,
},
car: {
type: CarType,
args: {
id: {
// example of using GraphQLNonNull to make the id required
type: new GraphQLNonNull(GraphQLString)
},
},
resolve: (parent, args) => cars.find(car => car.id === args.id),
}
Check the docs for more examples and options.

Categories

Resources