I have a data object below.
{
name: "Catherine Myer",
age: 23,
birthday: "august"
}
If in need to pass the data as a prop to a component, BUT would also like to change just the age to: 24. How do i do so?
<NextPage data={author.age = 24}/>
I need the final object to be:
{
name: "Catherine Myer",
age: 24,
birthday: "august"
}
You can do it with spread syntax:
<NextPage data={{...author, age: 24}}/>
Either pass individual prop values by spreading author (see Spread Attributes) and override age with a separate prop, eg
const NextPage = ({ name, age, birthday }) => {
// ...
};
<NextPage {...author} age="24" />
or extend the existing object and provide a new age property
const NextPage = ({ data: { name, age, birthday } }) => {
// ...
};
<NextPage data={{...author, age: 24}} />
You can just use the JS spread syntax to update whichever properties you need.
const author = {
name: "Catherine Myer",
age: 23,
birthday: "august"
};
const data = {
age: 24
};
const updatedAuthor = { ...author, ...data };
Edit: I have no idea what I was thinking to make it this complicated...
If you don't know which property will be overwritten, a simple for in loop can make the update. As a bonus, this scales up if you want to modify the value of more than one property at once.
Alternatively, if you really want to (or if you make the change Mike Kamermans recommended), you can use the JS spread syntax to achieve the same.
const author = {
name: "Catherine Myer",
age: 23,
birthday: "august"
};
const data = {
age: 24
};
// OPTION 1: for in loop
let updatedAuthor = { ...author }; // optionally create a copy to avoid mutating the original object
for(let prop in data) {
updatedAuthor[prop] = data[prop];
}
// OPTION 2: spread syntax
const propToUpdate = Object.keys(update)?.[0];
const updatedAuthor = {
...author,
[propToUpdate]: update[propToUpdate]
}
Related
Let's suppose I have the following object:
const user = {
id: 42,
displayName: "jdoe",
fullName: {
firstName: "John",
lastName: "Doe"
}
};
And that I want only the id and fullName.
I will do the following :
const { id, fullName } = user
Easy-peasy, right?
Now let's suppose that I want to do the destructuring based on the value of another variable called fields.
const fields = [ 'id', 'fullName' ]
Now my question is : How can I do destructuring based on an array of keys?
I shamelessly tried the following without success:
let {[{...fields}]} = user and let {[...fields]} = user. Is there any way that this could be done?
Thank you
It's not impossible to destructure with a dynamic key. To prevent the problem of creating dynamic variables (as Ginden mentioned) you need to provide aliases.
const user = {
id: 42,
displayName: "jdoe",
fullName: {
firstName: "John",
lastName: "Doe"
}
};
const fields = [ 'id', 'fullName' ];
const object = {};
const {[fields[0]]: id, [fields[1]]: fullName} = user;
console.log(id); // 42
console.log(fullName); // { firstName: "John", lastName: "Doe" }
To get around the problem of having to define static aliases for dynamic values, you can assign to an object's dynamic properties. In this simple example, this is the same as reverting the whole destructuring, though :)
const user = {
id: 42,
displayName: "jdoe",
fullName: {
firstName: "John",
lastName: "Doe"
}
};
const fields = [ 'id', 'fullName' ];
const object = {};
({[fields[0]]: object[fields[0]], [fields[1]]: object[fields[1]]} = user);
console.log(object.id); // 42
console.log(object.fullName); // { firstName: "John", lastName: "Doe" }
sources:
https://twitter.com/ydkjs/status/699845396084846592
https://github.com/getify/You-Dont-Know-JS/blob/master/es6%20%26%20beyond/ch2.md#not-just-declarations
Paul Kögel's answer is great, but I wanted to give a simpler example for when you need only the value of a dynamic field but don't need to assign it to a dynamic key.
let obj = {x: 3, y: 6};
let dynamicField = 'x';
let {[dynamicField]: value} = obj;
console.log(value);
Short answer: it's impossible and it won't be possible.
Reasoning behind this: it would introduce new dynamically named variables into block scope, effectively being dynamic eval, thus disabling any performance optimization. Dynamic eval that can modify scope in fly was always regarded as extremely dangerous and was removed from ES5 strict mode.
Moreover, it would be a code smell - referencing undefined variables throws ReferenceError, so you would need more boilerplate code to safely handle such dynamic scope.
As discussed before, you can't destruct into dynamically named variables in JavaScript without using eval.
But you can get a subset of the object dynamically, using reduce function as follows:
const destruct = (obj, ...keys) =>
keys.reduce((a, c) => ({ ...a, [c]: obj[c] }), {});
const object = {
color: 'red',
size: 'big',
amount: 10,
};
const subset1 = destruct(object, 'color');
const subset2 = destruct(object, 'color', 'amount', 'size');
console.log(subset1);
console.log(subset2);
You can't destruct without knowing the name of the keys or using an alias for named variables
// you know the name of the keys
const { id, fullName } = user;
// use an alias for named variables
const { [fields[0]]: id, [fields[1]]: fullName } = user;
A solution is to use Array.reduce() to create an object with the dynamic keys like this:
const user = {
id: 42,
displayName: "jdoe",
fullName: {
firstName: "John",
lastName: "Doe"
}
};
const fields = [ 'id', 'fullName', 'age' ];
const obj = fields.reduce((acc, k) => ({ ...acc, ...(user.hasOwnProperty(k) && { [k]: user[k] }) }), {});
for(let k in obj) {
console.log(k, obj[k]);
}
I believe that the above answers are intellectual and valid because all are given by pro developers. :). But, I have found a small and effective solution to destructure any objects dynamically. you can destructure them in two ways. But both ways are has done the same action.
Ex:
const user = {
id: 42,
displayName: "jdoe",
fullName: {
firstName: "John",
lastName: "Doe"
}
};
using "Object.key", "forEach" and "window" object.
Object.keys(user).forEach(l=>window[l]=user[l]);
Simply using Object. assign method.
Object.assign(window, user)
Output:
console.log(id, displayName, fullName)
// 42 jdoe {firstName: "John", lastName: "Doe"}
Anyway, I am a newbie in JS. So, don't take it as an offense if you found any misleading info in my answer.
I have this code that set the obj value in localstorage.
const obj = {
name: "Bill",
meta: {
age: 18
}
};
const data = localStorage.setItem('user', JSON.stringify(obj));
Now i want to change the age key in the localstorage:
localStorage.setItem('user', JSON.stringify({ ...data, ...data.meta.age= 15 } }));, but it does not work.
How to change the value above and to see the changes in localstorage?
Assuming you have data, the problem is that ...data.meta.age = 15 is a syntax error. You don't use = in object literals, and it does't make sense to try to spread the age property (which is a number). Instead:
const newData = {
...data,
meta: {
...data.meta,
age: 15,
},
};
localStorage.setItem("user", JSON.stringify(newData));
Notice how we have to create a new outermost object and also a new object for meta.
Live Example:
const data = {
name: "Bill",
meta: {
occupation: "Programmer", // Added so we see it get copied
age: 18,
},
};
const newData = {
...data,
meta: {
...data.meta,
age: 15,
},
};
console.log(newData);
Following code outputs {name: "Bob", surname: "Smith"} and it works fine. I want to know can I make it shorter.
((person = { name: 'Bob', surname: 'Smith', age: 22, }) => {
const {
name, // (a) create variable from deconstructing
surname,
} = person;
return {
name, // (b) reuse variable as new object parameter name (and value)
surname
}
})();
Can I somehow merge object deconstruction to variables (a) with returning a new object with Object Property Value shorthand (b)?
I use here shorthand but then its purpose is defeated by the need to manually re-use parameters. I want to mention the name or surname word in my function once not twice...
Destructure person in the function's declaration:
const result = (({ name, surname } = { name: 'Bob', surname: 'Smith', age: 22, }) => ({
name, // (b) reuse variable as new object parameter name (and value)
surname
}))();
console.log(result);
You can not mention it at all
((person = { name: 'Bob', surname: 'Smith', age: 22, }) => {
const {age,...ans} = person;
return ans
})()
Let's suppose I have the following object:
const user = {
id: 42,
displayName: "jdoe",
fullName: {
firstName: "John",
lastName: "Doe"
}
};
And that I want only the id and fullName.
I will do the following :
const { id, fullName } = user
Easy-peasy, right?
Now let's suppose that I want to do the destructuring based on the value of another variable called fields.
const fields = [ 'id', 'fullName' ]
Now my question is : How can I do destructuring based on an array of keys?
I shamelessly tried the following without success:
let {[{...fields}]} = user and let {[...fields]} = user. Is there any way that this could be done?
Thank you
It's not impossible to destructure with a dynamic key. To prevent the problem of creating dynamic variables (as Ginden mentioned) you need to provide aliases.
const user = {
id: 42,
displayName: "jdoe",
fullName: {
firstName: "John",
lastName: "Doe"
}
};
const fields = [ 'id', 'fullName' ];
const object = {};
const {[fields[0]]: id, [fields[1]]: fullName} = user;
console.log(id); // 42
console.log(fullName); // { firstName: "John", lastName: "Doe" }
To get around the problem of having to define static aliases for dynamic values, you can assign to an object's dynamic properties. In this simple example, this is the same as reverting the whole destructuring, though :)
const user = {
id: 42,
displayName: "jdoe",
fullName: {
firstName: "John",
lastName: "Doe"
}
};
const fields = [ 'id', 'fullName' ];
const object = {};
({[fields[0]]: object[fields[0]], [fields[1]]: object[fields[1]]} = user);
console.log(object.id); // 42
console.log(object.fullName); // { firstName: "John", lastName: "Doe" }
sources:
https://twitter.com/ydkjs/status/699845396084846592
https://github.com/getify/You-Dont-Know-JS/blob/master/es6%20%26%20beyond/ch2.md#not-just-declarations
Paul Kögel's answer is great, but I wanted to give a simpler example for when you need only the value of a dynamic field but don't need to assign it to a dynamic key.
let obj = {x: 3, y: 6};
let dynamicField = 'x';
let {[dynamicField]: value} = obj;
console.log(value);
Short answer: it's impossible and it won't be possible.
Reasoning behind this: it would introduce new dynamically named variables into block scope, effectively being dynamic eval, thus disabling any performance optimization. Dynamic eval that can modify scope in fly was always regarded as extremely dangerous and was removed from ES5 strict mode.
Moreover, it would be a code smell - referencing undefined variables throws ReferenceError, so you would need more boilerplate code to safely handle such dynamic scope.
As discussed before, you can't destruct into dynamically named variables in JavaScript without using eval.
But you can get a subset of the object dynamically, using reduce function as follows:
const destruct = (obj, ...keys) =>
keys.reduce((a, c) => ({ ...a, [c]: obj[c] }), {});
const object = {
color: 'red',
size: 'big',
amount: 10,
};
const subset1 = destruct(object, 'color');
const subset2 = destruct(object, 'color', 'amount', 'size');
console.log(subset1);
console.log(subset2);
You can't destruct without knowing the name of the keys or using an alias for named variables
// you know the name of the keys
const { id, fullName } = user;
// use an alias for named variables
const { [fields[0]]: id, [fields[1]]: fullName } = user;
A solution is to use Array.reduce() to create an object with the dynamic keys like this:
const user = {
id: 42,
displayName: "jdoe",
fullName: {
firstName: "John",
lastName: "Doe"
}
};
const fields = [ 'id', 'fullName', 'age' ];
const obj = fields.reduce((acc, k) => ({ ...acc, ...(user.hasOwnProperty(k) && { [k]: user[k] }) }), {});
for(let k in obj) {
console.log(k, obj[k]);
}
I believe that the above answers are intellectual and valid because all are given by pro developers. :). But, I have found a small and effective solution to destructure any objects dynamically. you can destructure them in two ways. But both ways are has done the same action.
Ex:
const user = {
id: 42,
displayName: "jdoe",
fullName: {
firstName: "John",
lastName: "Doe"
}
};
using "Object.key", "forEach" and "window" object.
Object.keys(user).forEach(l=>window[l]=user[l]);
Simply using Object. assign method.
Object.assign(window, user)
Output:
console.log(id, displayName, fullName)
// 42 jdoe {firstName: "John", lastName: "Doe"}
Anyway, I am a newbie in JS. So, don't take it as an offense if you found any misleading info in my answer.
Let's suppose I have the following object:
const user = {
id: 42,
displayName: "jdoe",
fullName: {
firstName: "John",
lastName: "Doe"
}
};
And that I want only the id and fullName.
I will do the following :
const { id, fullName } = user
Easy-peasy, right?
Now let's suppose that I want to do the destructuring based on the value of another variable called fields.
const fields = [ 'id', 'fullName' ]
Now my question is : How can I do destructuring based on an array of keys?
I shamelessly tried the following without success:
let {[{...fields}]} = user and let {[...fields]} = user. Is there any way that this could be done?
Thank you
It's not impossible to destructure with a dynamic key. To prevent the problem of creating dynamic variables (as Ginden mentioned) you need to provide aliases.
const user = {
id: 42,
displayName: "jdoe",
fullName: {
firstName: "John",
lastName: "Doe"
}
};
const fields = [ 'id', 'fullName' ];
const object = {};
const {[fields[0]]: id, [fields[1]]: fullName} = user;
console.log(id); // 42
console.log(fullName); // { firstName: "John", lastName: "Doe" }
To get around the problem of having to define static aliases for dynamic values, you can assign to an object's dynamic properties. In this simple example, this is the same as reverting the whole destructuring, though :)
const user = {
id: 42,
displayName: "jdoe",
fullName: {
firstName: "John",
lastName: "Doe"
}
};
const fields = [ 'id', 'fullName' ];
const object = {};
({[fields[0]]: object[fields[0]], [fields[1]]: object[fields[1]]} = user);
console.log(object.id); // 42
console.log(object.fullName); // { firstName: "John", lastName: "Doe" }
sources:
https://twitter.com/ydkjs/status/699845396084846592
https://github.com/getify/You-Dont-Know-JS/blob/master/es6%20%26%20beyond/ch2.md#not-just-declarations
Paul Kögel's answer is great, but I wanted to give a simpler example for when you need only the value of a dynamic field but don't need to assign it to a dynamic key.
let obj = {x: 3, y: 6};
let dynamicField = 'x';
let {[dynamicField]: value} = obj;
console.log(value);
Short answer: it's impossible and it won't be possible.
Reasoning behind this: it would introduce new dynamically named variables into block scope, effectively being dynamic eval, thus disabling any performance optimization. Dynamic eval that can modify scope in fly was always regarded as extremely dangerous and was removed from ES5 strict mode.
Moreover, it would be a code smell - referencing undefined variables throws ReferenceError, so you would need more boilerplate code to safely handle such dynamic scope.
As discussed before, you can't destruct into dynamically named variables in JavaScript without using eval.
But you can get a subset of the object dynamically, using reduce function as follows:
const destruct = (obj, ...keys) =>
keys.reduce((a, c) => ({ ...a, [c]: obj[c] }), {});
const object = {
color: 'red',
size: 'big',
amount: 10,
};
const subset1 = destruct(object, 'color');
const subset2 = destruct(object, 'color', 'amount', 'size');
console.log(subset1);
console.log(subset2);
You can't destruct without knowing the name of the keys or using an alias for named variables
// you know the name of the keys
const { id, fullName } = user;
// use an alias for named variables
const { [fields[0]]: id, [fields[1]]: fullName } = user;
A solution is to use Array.reduce() to create an object with the dynamic keys like this:
const user = {
id: 42,
displayName: "jdoe",
fullName: {
firstName: "John",
lastName: "Doe"
}
};
const fields = [ 'id', 'fullName', 'age' ];
const obj = fields.reduce((acc, k) => ({ ...acc, ...(user.hasOwnProperty(k) && { [k]: user[k] }) }), {});
for(let k in obj) {
console.log(k, obj[k]);
}
I believe that the above answers are intellectual and valid because all are given by pro developers. :). But, I have found a small and effective solution to destructure any objects dynamically. you can destructure them in two ways. But both ways are has done the same action.
Ex:
const user = {
id: 42,
displayName: "jdoe",
fullName: {
firstName: "John",
lastName: "Doe"
}
};
using "Object.key", "forEach" and "window" object.
Object.keys(user).forEach(l=>window[l]=user[l]);
Simply using Object. assign method.
Object.assign(window, user)
Output:
console.log(id, displayName, fullName)
// 42 jdoe {firstName: "John", lastName: "Doe"}
Anyway, I am a newbie in JS. So, don't take it as an offense if you found any misleading info in my answer.