How i push an item to nested object? - javascript

I have an object defined like this. I want to access the role object and push a value into it. I couldn't do it with a map anyway. Any help?
Example: That exactly what i want. I want to map and find role and push some items. I filter the object if there is the same element i just change its value
interface IInitial {
init: string;
lang: string;
}
interface IInitialValues {
role: IInitial[];
addPrivs: string;
}
const [initialValues, setInitialValues] = useState<IInitialValues[]>([]);
initialValues.map((item) => item.role)
.push({
init: "test",
lang: "TR",
})
OR
initialValues
.map((item: any) => item === name)
.filter((item: any) => {
if (item.lang === activeLang) {
item.init = value;
}
});

You use state so you have to return new collection, and not modify the initial collection
///Update the state
setInitialValues(prevValues =>{
return prevValues.map(item => {
///rule to find the item to add roles to
if (item.addPrivs === 'somethig') {
///return cloned object with one more role item
return {...item, roles:[...item.role, { init: 'newInit', lang: 'new lang' } ] }
} else {
/// does not match the rule return unmodified item
return item;
}
} )
} )

initialValues.map((item) => item.role)
.push(...initialValues, {
init: "test",
lang: "TR",
})

Related

React extracting a nested json object

How can I extract the 'jobs' object from a nested json list like this:
result:
{
person:
[
{
name: ""
address: ""
jobs: [
{
company:""
},
{
company:""
}
]
}
]
}
Thank you
Write a generic method to extract object properties.
function onExtract(key, data) {
if (isObject(data)) {
for (let item in data) {
if (key === item) {
return data[item];
}
const res = onExtract(key, data[item]);
if (res !== null) return res;
}
}
if (isArray(data)) {
for (let item of data) {
const res = onExtract(key, item);
if (res !== null) return res;
}
}
return null;
}
function isObject(obj) {
return Object.prototype.toString.call(obj) === "[object Object]";
}
function isArray(arr) {
return Object.prototype.toString.call(arr) === "[object Array]";
}
// test
const data = {
person: [
{
name: "",
address: "",
jobs: [
{
company: ""
},
{
company: ""
}
]
}
]
};
console.log(onExtract("jobs", data));
let's say you have a return var that contains this json value
let mappedCompanies = return.person.map(person =>
person.jobs.map(job => job.company)
).flatMap(m => m)
mappedCompanies would contain an array with all the companies names for each one of the registers in "person", all as one array of strings
you can read more about Array.map() here: https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Array/map
A dynamic way to query the person[] and find jobs, is to use the javascript map() method.
Here is the code without comments.
const personsJobs = (personName, personAddress) => {
const jobs = result.person.map((el) => {
if (el.name === personName && el.address === personAddress) {
return el.jobs;
} else {
return null;
}
})
.filter((el) => el !== null);
return jobs;
};
console.log(personsJobs("wyatt", "1234 test ln"));
Here is the code with comments to explain how the personsJob function works.
// Blow is an ES6 arrow function with the parameters 'personName' and 'personAddress',
// which represents the person in which you are querying for jobs (using both a persons
// name and address so in the case of persons with the same name, you only find the jobs
// of the person you want).
const personsJobs = (personName, personAddress) => {
// Since 'person' is an array, we can use the 'map' method as stated before, which
// will create a new array (jobs) that will store the jobs a specific person has.
const jobs = result.person.map((el) => {
// el stands for the current position in the person array.
// if el's (the current person) name and address values are equal to that of the
// parameters personName and personAddress, then that persons jobs are added to the jobs // array, however, if el does not satisfy the two parameters, null is added to the jobs
// array.
// The array, upon completion, will look something like this: ["programmer", null, null]
if (el.name === personName && el.address === personAddress) {
return el.jobs;
} else {
return null;
}
})
// Finally, the filter method is called to remove all null values so that you will
// only have the persons job in the jobs array.
// After filtering, the array will look like this: ["programmer"]
.filter((el) => el !== null);
return jobs;
};
// Prints the array of wyatt's jobs
console.log(personsJobs("wyatt", "1234 test ln"));
So, following the conclusion of the function, you will have dynamically found the jobs of a specific person.
you can use flatMap function like:
const jobsData = result.person.flatMap(item => item.jobs);
Here is a flexible solution using object-scan
// const objectScan = require('object-scan');
const data = { person: [{ name: '', address: '', jobs: [{ company: '' }, { company: '' }] }] };
console.log(objectScan(['person[*].jobs'], { reverse: false, rtn: 'value' })(data));
// => [ [ { company: '' }, { company: '' } ] ]
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan#14.0.0"></script>
Disclaimer: I'm the author of object-scan

Create new object from array

I'm trying to create new object with different properties name from Array.
Array is:
profiles: Array(1)
0:
column:
name: "profileName"
title: "Profile name"
status: "Active"
I want to create new function that return object with two properties:
id: 'profileName',
profileStatus: 'Active'
The function that I have create is returning only one property as undefined undefined=undefined.
function getProfile(profiles) {
if (!profiles.length) return undefined;
return profiles.reduce((obj, profile) => {
console.log('profiles', profile);
return ({
...obj,
id: profile.column.name,
profileStatus: profile.status,
});
}, {});
}
The function getProfile is taking as input array 'profiles' from outside,
I've just tested here and this seems to be working actually
const getProfile1 = (p) => p.reduce((obj, profile) =>({
...obj,
id: profile.column.name,
profileStatus: profile.status,
}), {});
You can use map as an alternative.
var profiles = [{"column":{"name": "profileName3","title": "3Profile name"},"status": "Active"},{"column":{"name": "profileName","title": "Profile name"},"status": "Active"}];
function getProfile(profiles) {
if (!profiles.length) return undefined;
return profiles.map(function(profile,v){
return {id:profile.column.name,profileStatus: profile.status};
});
}
console.log(getProfile(profiles));
Whenever I use reduce in this way, I usually index the final object by some sort of an id. As noted in another answer, you could use map in this situation as well. If you really want your final data structure to be an object, however, you could do something like this:
/**
* returns object indexed by profile id
*/
const formatProfiles = (profiles) => {
return profiles.reduce((obj, profile) => {
return {
...obj,
[profile.id]: {
id: profile.column.name,
profileStatus: profile.status,
}
};
}, {});
};
const profiles = [
{
id: 0,
status: 'active',
column: {
name: "profile_name_1",
title: "profile_title_1",
},
},
{
id: 1,
status: 'inactive',
column: {
name: "profile_name_2",
title: "profile_title_2",
}
}
];
const result = formatProfiles(profiles);
/**
* Result would look like this:
*/
// {
// '0': { id: 'profile_name_1', profileStatus: 'active' },
// '1': { id: 'profile_name_2', profileStatus: 'inactive' }
// }

Edit function not saving changes to state data in React

I am trying to provide functionality in my webpage for editing state data.
Here is the state structure
state = {
eventList:[
{
name: "Coachella"
list: [
{
id: 1,
name: "Eminem"
type: "rap"
}
{
id: 2,
name: "Kendrick Lamar"
type: "rap"
}
]
}
]
}
I want to be able to edit the list arrays specifically the id, name, and type properties but my function doesn't seem to edit them? I currently pass data I want to override id name and type with in variable eventData and an id value specifying which row is selected in the table which outputs the state data.
Here is the function code:
editPickEvent = (eventData, id) => {
const eventListNew = this.state.eventList;
eventListNew.map((event) => {
event.list.map((single) => {
if (single.id == id) {
single = eventData;
}
});
});
this.setState({
eventList: eventListNew,
});
};
When I run the code the function doesn't alter the single map variable and I can't seem to pinpoint the reason why. Any help would be great
edit:
Implementing Captain Mhmdrz_A's solution
editPickEvent = (eventData, id) => {
const eventListNew = this.state.eventList.map((event) => {
event.list.map((single) => {
if (single.id == id) {
single = eventData;
}
});
});
this.setState({
eventList: eventListNew,
});
};
I get a new error saying Cannot read property list of undefined in another file that uses the map function to render the state data to the table?
This is the part of the other file causing the error:
render() {
const EventsList = this.props.eventList.map((event) => {
return event.list.map((single) => {
return (
map() return a new array every time, but you are not assigning it to anything;
editPickEvent = (eventData, id) => {
const eventListNew = this.state.eventList.map((event) => {
event.list.forEach((single) => {
if (single.id == id) {
single = eventData;
}
});
return event
});
this.setState({
eventList: eventListNew,
});
};
const editPickEvent = (eventData, id) => {
const updatedEventList = this.state.eventList.map(event => {
const updatedList = event.list.map(single => {
if (single.id === id) {
return eventData;
}
return single;
});
return {...event, list: updatedList};
});
this.setState({
eventList: updatedEventList,
});
}
Example Link: https://codesandbox.io/s/crazy-lake-2q6ez
Note: You may need to add more checks in between for handling cases when values could be null or undefined.
Also, it would be good if you can add something similar to the original data source or an example link.
Turns out primitive values are pass by value in javascript, which I didn't know and why the assignment wasn't working in some of the previous suggested answers. Here is the code that got it working for me:
editEvent = (EventData, id) => {
const eventListNew = this.state.eventList.map((event) => {
const newList = event.list.map((single) => {
return single.id == id ? EventData : single;
});
return { ...event, list: newList };
});
this.setState({
eventList: eventListNew,
});
};

Insert an item in a list inside another in react state

I have this variable on my state:
this.state = {
itemList: {
item: [
{
itemAlias: [
{
name: null
}
],
idItem: null,
itemName: null,
}
]
}
}
what I want to do is to insert a new item alias on a cetain item.I did this and its inserting a new itemAlias to my item but is also creates a new Item, and I dont want that, I just want to update my item with a new Item alias:
insertAliasToList = (itm) => {
let insertedAlias = {
name: 'test'
}
itm.itemAlias.push(insertedAlias)
this.setState(prevState => ({
...prevState,
itemList: {
...prevState.itemList,
item: [...prevState.itemList.item, p]
}
}))
}
I have also tried this but the error Uncaught TypeError: Invalid attempt to spread non-iterable instance appears.
insertAliasToList = (itm) => {
let insertedAlias = {
name: 'test'
}
// itm.itemAlias.push(insertedAlias)
this.setState(prevState => ({
...prevState,
itemList: {
...prevState.itemList,
item: {
...prevState.itemLIst.item,
itemAlias:[...prevState.itemList.item.itemAlias,insertedAlias]
}
}
}))
}
Thanks in advance!
Since you are trying to replace the contents of an item within an array, you will need to first duplicate the array. Then replace what you need within that item using the index and set the state again with the new array.
let insertedAlias = {
name: 'test'
}
// Duplicate 'item' array
const item = [...this.state.itemList.item]
// Change item using index '0' on the duplicated array
item[0] = {
...item[0],
itemAlias: [
...item[0].itemAlias,
insertedAlias,
]
}
// Set state with new item array that contains changes you made
this.setState(prevState => ({
...prevState,
itemList: {
...prevState.itemList,
item: [
...item,
]
}
}))
You can do something like this:
insertAliasToList = (itm) => {
let insertedAlias = {
name: 'test'
}
this.setState(prevState => ({
...prevState,
itemList: {
...prevState.itemList,
item: prevState.itemList.item.map(i => {
if (i.idItem === itm.idItem) {
return {
...i,
itemAlias: [...i.itemAlias, insertedAlias]
}
}
return i;
})
}
}))
}
It will only work if idItem is unique.

Can't Store Result of GraphQL Query - Always undefined

I am doing a query and have already logged the result. Everything works as it should, however when I want to continue working with the result it always is "undefined" (see 2nd logging).
I am sure I am missing out on something obvious here but would really love to get your help :)
render() {
let saved;
this.props.apolloClient
.watchQuery<Query>({
query: gql`
query($id: ID!) {
element(id: $id) {
children {
... on TextNote {
name
description
type
}
}
}
}
`,
variables: { id: 0 }
})
.subscribe(({ data: { element: { children } } }) => {
console.log(children); // this is the wanted result
saved = children;
});
console.log("save");
console.log(saved); // this is undefined for some reason
If children gives you the correct result, can you not just assign your variable saved to your this.props.apolloClient function and return children inside the subscribe call?
Something like:
render() {
const saved = this.props.apolloClient
.watchQuery<Query>({
query: gql`
query($id: ID!) {
element(id: $id) {
children {
... on TextNote {
name
description
type
}
}
}
}
`,
variables: { id: 0 }
})
.subscribe(({ data: { element: { children } } }) => {
console.log(children); // this is the wanted result
return children; // <-- return the value here
});
console.log("save");
console.log(saved); // <-- should have children assigned to saved

Categories

Resources