Conditional adding object property in JavaScript - javascript

axios.post('saveUser', {id, name})
If name is empty how could I exclude it in the param? if I put ({id, name}), isn't the method would still have a property of name undefined?
I don't want this
const obj = {id: 123, name: undefined}
I want this const obj = {id: 123}
but I don't want to create a temporary variable like so
let obj = { id: id }; if(name) obj = { ...obj, name };

I would suggest you adding object properties conditionally with ES6 syntax like this.
const normalizeData = ({id, name = ""}) => {
const condition = !!name; // Equivalent to: name !== undefined && name !== "";
return {id, ...(condition && { name })};
}
console.log(normalizeData({id: 123, name: ""}));
console.log(normalizeData({id: 123, name: undefined}));
console.log(normalizeData({id: 123, name: "Phong_Nguyen"}));
Explain:
Using Default function parameters at line code name = "" to avoid undefined of name propety having not included in input object.
Using Destructuring assignment at line code ...(condition && { name })

You can create the object with the id first and then add a name afterwards:
const obj = {id: 123};
if(name) obj.name = name;
axios.post('saveUser', obj);

Related

How can I manipulate key name in Object with Javascript

I want to do change the name of a key in an Object. But when I want to do this with an if condition, I get this (Assignment to function parameter 'key') error. How can i manipulate a key name ?
My Code:
const personData = [];
Object.keys(testItem).forEach((key) => {
item = testItem[key];
if (key === 'Name'){
key = 'Person Name';
}
personData.push({ name: key, data: Object.values(item) })
});
testItem data:
testItem = {Name: {...}, Surname: {...}}
I want the Name key to change to Person Name without error.
The key variable was taken in as input for the foreach function, and you shouldn't modify it - it is meant as a read only variable. An alternative that doesn't modify the key variable would be
const personData = [];
Object.keys(testItem).forEach((key) => {
let newKey = key;
item = testItem[key];
if (key === 'Name'){
newKey = 'Person Name';
}
personData.push({ name: newKey, data: Object.values(item) })
});
I didn't get what you wanted to do, simply assign keys value to new key and delete previous one for example :
const personData = {
Name: 'John',
lastname: 'Doe'
};
personData.PersonName = personData.Name
delete personData.Name;
console.log(personData.PersonName)

Can't implement simple optional chaining

I am trying to implement a simple optional chaining state update. What I want is for the items to ONLY be changed IF the item is defined/exists; if not/is undefined, I want the item to keep the previous state (e.g userID should remain = 2 if not updated).
To test this out I created an object with three variables:
const userObj = {
firstName: "",
lastName: "",
userID: 2,
};
Then I created a function to update state:
const updateState = (item) => {
return {
userObj.firstName = item?.firstName,
userObj.lastName = item?.lastName,
userObj.userID = item?.userID,
};
};
Finally I pass the item which contains only one item to update (firstName) and I call the function:
const item = {
firstName: "None",
};
console.log(updateState(item));
The output:
userObj.firstName = item?.firstName,
^
SyntaxError: Unexpected token '.'
But when I hover over userObj I can see its properties:
You get this error because what you are trying to return is an object with dots in its keys.
You're mixing assignment and object creation. In addition item?.firstName only helps with the case that item is null or undefined in a sense that it fails fast instead of throwing an exception because you can't access null.firstName.
For this kind of default you'd have to do something along the lines of typeof item.firstName === 'string' ? item.firstName : userObj.firstName.
To pull everything together:
const func = (value, fallback) => (
typeof value === typeof fallback
? value
: fallback
);
const updateState = (item) => {
userObj.firstName = func(item?.firstName, item.firstName);
userObj.lastName = func(item?.lastName, item.lastName);
userObj.userID = func(item?.userID, item.userId);
return userObj;
};
Note however that this function will mutate userObj.
Edit: default was a poor naming choice.
You can do it this way, using javascript object destructuring
const updateState = (item) => {
return {
...userObj,
...item,
};
};
so it will only update the key and value that was passed, i hope the question is not on typescript
You can use null coalescing in conjunction with optional chaining:
const updateState = item => ({
userObj.firstName = item?.firstName ?? userObj.firstName ,
userObj.lastName = item?.lastName ?? userObj.lastName ,
userObj.userID = item?.userID ?? userObj.userId ,
});
You could use the spread operator:
const updateState = item => {
userObj = { ...userObj, ...item };
return userObj;
}
Or you can use lodash's defaults() function:
const _ = require('lodash');
const updateState = item => {
userObj = _.defaults(userObj, item)
return userObj;
}
Or... if you really want to mutate the state object, rather than creating a new one and replacing it, roll your own, similar:
const updateState = item => {
for (const key in item ) {
const hasValue = key != null && key != undefined && key != NaN ;
if ( hasValue ) {
userObj[prop] = item[prop];
}
}
}
There is, as they say, more than one way to skin a cat.
[Edited: Add explanation of the spread operator]
The spread operator,
const obj = { ...obj1, ...obj2, . . . , ...objN };
is somewhat akin to calling a function like this:
const obj = mergeObjects( obj1, obj2, . . ., objN );
where mergeObjects() is defined as:
function mergeObjects(...objects) {
const mergedObject = {};
for (const obj of objects ) {
for (const key in obj ) {
mergedObject[key] = item[key];
}
}
return mergedObject;
}
Or perhaps a better explanation might be done using Object.assign(). One could say that an expression like:
const obj = {
prop1: 'a' ,
prop2: 'b' ,
...obj1 ,
prop3: 'c' ,
prop4: 'd' ,
...obj2 ,
prop5: 'e' ,
prop6: 'f' ,
...obj3 ,
}
is the equivalent of this:
const obj = Object.assign( {},
{
prop1: 'a' ,
prop2: 'b' ,
},
obj1 ,
{
prop3: 'c' ,
prop4: 'd' ,
} ,
obj2 ,
{
prop5: 'e' ,
prop6: 'f' ,
} ,
obj3 ,
);

destructuring nested level of array of object

I have an object where one property contains array of objects, I need to destructure it, but when destructuring I don't know how to handle if that property is of empty array
const dataTest1 = {
id: 1,
details: [{f_name_1: "John"}]
}
const {details : [{f_name_1}] = [{}]} = dataTest1 || {}
console.log(f_name_1 ?? 'NA')
const dataTest2 = {
id: 2
}
const {details : [{f_name_2}] = [{}]} = dataTest2 || {}
console.log(f_name_2 ?? 'NA')
const dataTest3 = {
id: 3,
details: []
}
const {details : [{f_name_3}] = [{}]} = dataTest3 || {}
console.log(f_name_3 ?? 'NA')
If you see the first and second case gives me value or fallback value, but when I pass details as an empty array its going error (dataTest3), because I am destructuring first position of array [{}], how can I give a default value as empty object
You need an object ad default value for the inner object, because you add only an array if the array is missing, but if exist, you have no object.
const dataTest3 = {
id: 3,
details: []
}
const { details: [{ f_name_3 } = {}] = [] } = dataTest3 || {};
console.log(f_name_3 ?? 'NA');

How to check for undefined when using find on an javascript array

In my array I am using .find to find an object and set its property to some value.
I want to set the name only if there is a value. i.e; check for undefined
Below is my array, am using .find to find the object and set its name.
I want to set only if the object with id === checkid is found.
this.myarray.find(colDef => colDef.id === checkid).name = newname;.
You can do this in one statement with Object.assign like this:
let myArray = [{id: 1, name: 'Boris'}, {id: 2}]
// id 3 does not exist no changes would be made to myArray
Object.assign(myArray.find(x => x.id == 3) || {}, {name: 'Foo'})
// id 1 is there so name would be changed to 'john'
Object.assign(myArray.find(x => x.id == 1) || {}, {name: 'john'})
console.log(myArray)
The idea is to provide Object.assign with an object literal if Array.find does not find an object with the provided id.
The other benefit of this is that you now pass an object for the update so you can easily update more than one property at a time:
let myArray = [{id: 1, name: 'Boris'}, {id: 2}]
// id 1 is there so name would be changed to 'john'
Object.assign(myArray.find(x => x.id == 1) || {}, {name: 'john', state: 'FL'})
console.log(myArray)
You need to run find as it's own statement and check if the result is defined. If so, assign the name, otherwise don't:
let myarray = [
{id: 100},
{id: 10},
{id: 5}
]
let found = myarray.find(colDef => colDef.id === 10)
if (found !== undefined){
found.name = "some name"
}
console.log(found)
// no id 11 found will be undefined
found = myarray.find(colDef => colDef.id === 11)
console.log(found)
As a single line:
this.myarray.find(colDef => colDef.id === checkid).name = newname;
there's no chance to check if find() returned undefined and trying to assign a property to undefined will be an error.
Here is both ways of approaching.
If you dont care, use fireAndForget style.
If you really want to know, a more verbose check.
const arr = [{id:1}];
const fireAndForget = (arr, id, newName) => (arr.find(i => i.id === id)||{}).name = newName;
const checkAndNotify = (arr, id, newName) => {
const p = arr.find(i => i.id === id);
if(!p) return false;
p.name = newName;
return true;
};
console.log(checkAndNotify(arr, 2, 'test'));
console.log(checkAndNotify(arr, 1, 'test'));
console.log(arr);
console.log(fireAndForget(arr, 2, 'test2'));
console.log(fireAndForget(arr, 1, 'test2'));
console.log(arr);
/Check if obj isn't null of undefined, and if it's an object. If if is a valid object, then assign the value for '.name'
const obj = this.myarray.find(colDef => colDef.id === checkid);
if (obj && typeof obj === "object") {
obj.name = newName;
}

How to safely destructure a JavaScript object in TypeScript

I want to pull out attributes from a JavaScript object (below) but want to protect myself from either the object being null or undefined as well as the properties not existing. That is, I want the values to just be undefined and not have the JavaScript error.
const {id,username,userFirstName,userLastName} = attendeeResults;
You can use logical operators to achieve that:
const nullObject = null;
const { foo, bar } = nullObject || {};
console.log(foo, bar);
JavaScript allow you to define default value when destructuring an object.
For example:
const {id: 0,username:'',userFirstName:'',userLastName:''} = attendeeResults;
But destruncturing throws an error if your attendeeResults object is null or undefined.
You could use the following, Please notice that i omitted username in the attendee to show that it keeps the null value.
const attendeeResults = { id: 1, userFirstName: 'John', userLastName: 'Smith'}
const obj = {
id: null,
username: null,
userFirstName: null,
userLastName: null
};
Object.assign(obj, attendeeResults);
console.log(obj);
This can be done this way:
const {id, username, ...rest} = {id: 10, username: 'u', firstname:'behzad',lastname:'besharati'};
console.log(id,username,rest);

Categories