Is there any way to use array contents in object destructuring - javascript

I have an array containing elements I want to destructure it and use them as object destructuring.
I have this code in which I am destructuring keys from req.body.
const {
city,
companyName,
contactName,
contactTitle,
country,
email,
fax,
password,
phone,
role,
} = req.body;
And I want to use an array for this all data,
eg.
const temp = [
city,
companyName,
contactName,
contactTitle,
country,
email,
fax,
password,
phone,
role,
];
and use this array as keys in object destructuring
According to me:
const { [... temp ]} = req.body;
I know this is wrong but is there something I can use this array and destructure that elements from req.body.

As Rajesh mentioned in the comments, you can't do that.
Object deconstruction is some sugar syntax to help you write cleaner code in most of the use cases. In your case, since you want something kinda specific (re-use a list of attributes names), you could create your own function that would mimic the behavior you want :
function extractVars(from) {
const myVarList = [
'city',
'companyName',
'contactName',
'contactTitle',
'country',
'email',
'fax',
'password',
'phone',
'role'
];
const vars = {};
for (let v of myVarList) {
vars[v] = from[v];
}
return vars;
}
const vv = extractVars(req.body);

Assuming req.body is an object containing all the key/values, and you just want the values in the temp array, try:
const temp = Object.values(req.body)
If you also want the keys exposing as variables in the containing function's
scope, you're best to create a temp object to store them, e.g.:
let tempObj = {}
Object.keys(req.body).forEach(key => { tempObj[key] = req.body[key] })
tempObj will then contain the key/values, e,g. tempObj.city, tempObj.companyName.
Hope this helps!

Related

Javascript object declaration with ternary operator

I'm declaring an object inside one of my components like below:
const data = {
user: id,
userRole: role,
teacherdepartment: department
}
But now I wanted to do this declaration dynamically depends on a specific value, like below:
let usertype='teacher';
const data = {
user: id,
userRole: role,
if(usertype=='teacher'?(teacherdepartment:tdepartment):(studentDepartment:sdepartment))
}
Is this possible. I know I can do it with nested ternary operator. But inside the object structure any simple line that can do that trick?
Update: object values can be easily set using ternary inside the object declaration, but this is for object key so this is not a duplicate of this. Also, in the above example I have put a simple object. Image if the objects have some child and ternary conditions within.
I think this could be refactored into
let usertype = 'teacher';
let departmentProperty = usertype === 'teacher' ? 'teacherdepartment' : 'studentDepartment';
let departmentValue = usertype === 'teacher' ? 'teacherdepartmentValue' : 'studentDepartment';
const data = {
user: 'id',
userRole: 'role',
[departmentProperty]: departmentValue,
};
console.log(data)
Try with conditional operator for both key and value. Keys can be made dynamic by adding [] around the key expression.
Pseude Code
const data = {
user: id,
userRole: role,
[usertype=='teacher'? 'teacherdepartment' : 'studentDepartment']: usertype=='teacher'? tdepartment: sdepartment,
}
Working Code
const usertype = 'student';
const tdepartment = 'tdepartment';
const sdepartment = 'sdepartment';
const id = 'id';
const role = 'role';
const data = {
user: id,
userRole: role,
[usertype=='teacher'? 'teacherdepartment' : 'studentDepartment']: usertype=='teacher'? tdepartment: sdepartment,
};
console.log(data)
I'd avoid a ternary operator altogether because they're confusing to read in a lot of situations. Instead I would create a dictionary that maps user types to string values, and then create the property dynamically with that information.
const userType = 'teacher';
const dict = { teacher: 'tdepartment', student: 'sdepartment' };
const data = {
user: 'id',
userRole: 'role',
[`${userType}Department`]: dict[userType]
}
console.log(data);
While this can be done in a "one-liner" IMO to preserve readability it shouldn't be.
Instead, check usertype and create an object to include in the resulting data object. This way the changes based on usertype are isolated and easy to reason about. It also allows for additional changes based on usertype as it's isolated from the static properties.
const deptInfo = usertype === 'teacher' ? { teacherDepartment: tDepartment }
: { studentDepartment: sDepartment }
const data = {
...deptInfo,
user: id,
userRole: role,
}

From single array convert to an array of object with keys coming from a JSON response -JAVASCRIPT-

I am receiving a json response from an API call. I need to store its keys, and create an array of an object. I am intending to this array of an object is created dynamically no matter the keys of the response.
I've already got the keys like this:
const json_getAllKeys = data => {
const keys = data.reduce((keys, obj) => (
keys.concat(Object.keys(obj).filter(key => (
keys.indexOf(key) === -1))
)
), [])
return keys
}
That returned an array (using a sample json):
['name','username', 'email']
But I am trying to use that array to create an array of object that looks like this one
[
{
name: "name",
username: "username",
email: "Email",
}
];
I've been trying mapping the array, but got multiple objects because of the loop, and I need a single one to make it work.
keys.map(i=>({i:i}))
[
{ i: 'id' },
{ i: 'name' },
{ i: 'username' },
{ i: 'email' }
]
Any hint would be useful!
Thanks in advance :D
What you're looking for is Object.fromEntries, which is ECMA2019, I believe, so available in Node >=14 and will be provided as a polyfill if you employ babel.
I can't quite discern what your reduce should produce, but given the sample input, I would write
const input = ['name','username', 'email'];
const result = Object.fromEntries(input.map(name => ([name, name])));
// result == { name: 'name', username: 'username', email: 'email' }
You're definitely on the right track. One thing to remember is the map function will return the SAME number of output as input. So in your example, an array of 3 returns an array of 3 items.
For this reason, map alone is not going to give you what you want. You may be able to map => reduce it. However, here is a way using forEach instead. This isn't a strictly functional programming style solution, but is pretty straight forward and depending on use case, probably good enough.
let keys = ['name','username', 'email'] //you have this array
const obj = {}; // empty object to hold result
keys.forEach(i => {
obj[i] = i; // set the object as you want
})
console.log(obj); // log out the mutated object
// { name: 'name', username: 'username', email: 'email' }

React object property value being duplicated on .push inside loop

I have a handleCreate function that takes care of taking some user data and inserting it into a database.
Inside the aliasArr.forEach() loop I POST into my DB new user instances for each element in the aliasArr array. This particular code works as expected, if I check the DB, I will find the new members.
After saving the new members, I want to keep the members in the members array so I can pass it along to another function.
For this, I'm doing members.push(memberAttributes); but if I log the contents of members I get the right amount of elements but the alias property value is duplicated (all other properties should have the same value cause they are being added into the same role in a batch operation).
If I have two new users, say: xyz and abc, I get:
[
{alias: "abc", Role: "admin", "grantedBy": "someone"},
{alias: "abc", Role: "admin", "grantedBy": "someone"},
]
Instead of:
[
{alias: "xyz", Role: "admin", "grantedBy": "someone"},
{alias: "abc", Role: "admin", "grantedBy": "someone"},
]
Here's the code:
handleCreate = () => {
const { memberAttributes } = this.state;
const { role, createRoleMember } = this.props;
const roleArr = [];
roleArr.push(role);
const aliasArr = memberAttributes.alias.split(",");
let members = [];
//false hardcoded during debugging.
if (false /* await aliasIsAdmin(memberAttributes.alias, roleArr) */) {
this.setState({ userExists: true });
} else {
memberAttributes["Granted By"] = window.alias;
memberAttributes.Role = role;
memberAttributes.timestamp = Date.now().toString();
this.handleClose();
aliasArr.forEach((currAlias) => {
memberAttributes.alias = currAlias;
console.log("memberAttributes:", memberAttributes);
members.push(memberAttributes);
console.log("members", members);
const marshalledObj = AWS.DynamoDB.Converter.marshall(memberAttributes);
const params = {
TableName: "xxx",
Item: marshalledObj,
};
axios.post(
"https://xxx.execute-api.us-west-2.amazonaws.com/xxx/xxx",
params
);
});
}
createRoleMember(members); //passing members to this function to do more stuff.
};
I'm wondering if this issue is due to memberAttributes being part of the component's state.
The problem here is that you are pushing references to the same object into the array after changing a value within that object. So whenever you make the change to memberAttributes.alias, it's changing the alias to the most recent one. After that, all references to the same object (which in this case is every item in the members array) present the new value in alias.
const obj = { alias: 'abc', role: 'role1' }
const arr = []
arr.push(obj)
obj.alias = 'new alias'
arr.push(obj)
for (var mem of arr) {
console.log(mem)
}
To fix it, you need to create a new object each time and push it onto the array instead, like so:
aliasArr.forEach((currAlias) => {
// Creates a new object in memory with the same values, but overwrites alias
const newMemberAttributes = Object.assign(memberAttributes, { alias: currAlias });
console.log("memberAttributes:", newMemberAttributes);
members.push(newMemberAttributes);
console.log("members", members);
...
}
Similarly, you can use the spread operator to create a deep copy of the object and then reassign alias.
aliasArr.forEach((currAlias) => {
// Creates a new object in memory with the same values, but overwrites alias
const newMemberAttributes = { ...memberAttributes };
newMemberAttributes.alias = currAlias
console.log("memberAttributes:", newMemberAttributes);
members.push(newMemberAttributes);
console.log("members", members);
...
}

Best way to rename object properties in ES6

I'm still learning js and I need an advice. I get json object from backend, but keys have underscores. What is best practice to rename keys to, for example folder_name to Folder name? The list of properties is known and finished so I can keep new names in constants. At frontend I already use it like this:
const showPropertiesList = properties => Object.keys(properties).map(property => (
<PropertyKey key={property}}>
`${property}: ${properties[property]}`
</PropertyKey>
));
It's better to use rename function in this map or create separate function before to get all renamed keys with values?
json file:
properties {
folder_name: 'test',
user_email: 'test#example.com',
user_agreed: 1,
site: 'example.com',
}
You can create some kind of a mapping object and then use the following combination of Object.keys and reduce functions:
const properties = {
folder_name: "test",
user_email: "test#example.com",
user_agreed: 1,
site: "example.com"
};
const mapping = {
folder_name: "Folder name",
user_email: "User email",
user_agreed: "User agreed",
site: "Site"
};
const mapped = Object.keys(properties).reduce((acc, key) => {
acc[mapping[key]] = properties[key];
return acc;
}, {});
console.log(mapped);
try this:
const { folder_name: folderName, user_email: email, ...others } = originObject;
const renamedPropsObject = { folderName, email, ...others }
Am traveling so I can’t program atm. But I think this will drive you in the correct direction.
let newArray = array()
oldArray.forEach(function(value, key) {
// do stuff here to change the key value
let newKeyValue = //something
newArray[newKeyValue] = value;
});
// do stuff with newArray
Hope it helps. Not tester it!
Mapping is a good approach, as the previous answer specifies.
In your case you can also do the renaming inline:
const showPropertiesList = properties => Object.keys(properties).map(property => (
<PropertyKey key={property}}>
`${property.replace('_', ' ')}: ${properties[property]}`
</PropertyKey>
));
Depending on if you want it changed everywhere or just where presented to the user

Pulling the same value out of a series of keys

I'm trying to quickly pull out ‘value’ property from some objects using destructuring.. is there a simple way to get it from this? I think it might be possible with some complicated destructuring thing i haven’t quite grocked.
I know I could use loops and such, but I'd like to make it a bit more elegant. I'm looking for a non-repetitive, ideally 1-2 line solution. I wanted to use a map, but that only works on an array...
formData = {
name: {val: 'myName', key: 'value', etc: 'more data'}
province: {val: 'myProvince', key: 'value', etc: 'more data'}
dateOfBirth: {val: 'myBDAY!', key: 'value', etc: 'more data'}
}
//desired outcome:
{
name: 'myName',
province: 'myProvince',
dateOfBirth: 'myBDAY!'
}
//attempt 1
let customer = { name, province, dateOfBirth} = formData; //hrm doesn't get me there
Destructuring is used to assign multiple variables from different elements of an array or object, that's not what you're doing. You can just do:
let customer = {
name: formData.name.val,
province: formData.province.val,
dateOfBirth: formData.dateOfBirth.val
}
If you don't want to list all the properties explicitly, just use a loop.
let customer = {};
for (var k of Object.keys(formData)) {
customer[k] = formData[k].val;
}
A hard to read one-liner would be:
let customer = Object.keys(formData).reduce(
(acc, key) => Object.assign(acc, {[key]: formData[key].val}), {});
to grab .val off every value in the object, and return a new object with the same keys.
That's basically the equivalent of:
let customers = {};
for (const key of Object.keys(formData)) customers[key] = formData[key].val;
Since you didn't like Barmar's answer, you can use a combination of Object.keys and the resulting array's reduce method:
let customer = Object.keys(formData).reduce(function(acc, key) {
acc[key] = formData[key].val;
return acc;
}, {});
You said you wanted to use destructuring… so let's do that:
let customer = {};
for (let k in formData) ({[k]: {val: customer[k]}} = formData);
But really, avoid that, and use clear and readable property assignment instead :-)

Categories

Resources