How to destructure a nested object only when it has a value? - javascript

let notStudent, name, isRegistered
if (studentDetail && studentDetail.fields) {
({ notStudent, name, isRegistered } = studentDetail.fields)
}
Is there a way to write this logic without an if statement or in a succinct way?

You can destructure in this way. The tricky thing is when there is no fields property on studentDetail then javascript can throw an error, to tackle that case, you can set default empty object using || operator.
let studentDetail = {
fields: {
notStudent: '1',
name: '2',
isRegistered: true
}
}
let {
notStudent,
name,
isRegistered
} = (studentDetail && studentDetail.fields) || {};
console.log(notStudent);
console.log(name);
console.log(isRegistered);

You can destructure an empty default object in case your studentDetail.fields doesn't exist:
const { notStudent, name, isRegistered } = studentDetail?.fields ?? {};

Related

Javascript - Get object fields using a given array of keys

Given this object:
const userData = {
avatar: undefined,
name: "Raul",
username: "raulito",
celebrity: true
}
I need to implement a method that receives a list of keys (i.e., ["avatar", "name", "username"]) and get the corresponding values of the userData object, ignoring undefined values.
How can I do this using modern javascript syntax?
function denormalizeUserData(userData, ...fields) {
const denormalized = {};
// For each key (field), get its value from userData, ignoring if undefined
return denormalized;
}
So, if I do:
denormalizeUserData(userData, "avatar", "name");
The method must return me:
{
name: "Raul,
}
Ignoring avatar, as it is undefined.
This is my attempt. I need modern syntax.
const userData = {
avatar: undefined,
name: "Raul",
username: "raulito",
celebrity: true
}
function denormalizeUserData(userData, ...fields) {
const denormalized = {};
fields.forEach((key) => {
const value = userData[key];
if(typeof value !== "undefined") {
denormalized[key] = value;
}
})
return denormalized;
}
console.log(denormalizeUserData(userData, "celebrity", "name", "avatar"))
function denormalizeUserData(userData, ...fields) {
const denormalized = {};
for (const field of fields) {
if (userData[field] !== undefined) denormalized[field] = userData[field];
}
return denormalized;
}
Edit: in case someone says a code-only answer is blah blah blah
This is simple enough to be a simple code block.
You can get the object property/value pairs with Object.entries, then use Array.filter to filter out the pairs whose property name is not included in fields and whose value is undefined, then use Object.fromEntries to convert it back to an object.
const userData = {
avatar: undefined,
name: "Raul",
username: "raulito",
celebrity: true
}
function denormalizeUserData(userData, ...fields) {
return Object.fromEntries(Object.entries(userData).filter(e => fields.includes(e[0]) && e[1] != undefined))
}
console.log(denormalizeUserData(userData, "avatar", "name"))
Grab the Object.entries and build a new object if there is a value, and if the args array includes the key.
const userData = {
avatar: undefined,
name: "Raul",
username: "raulito",
celebrity: true
};
function denormalizeUserData(obj, ...args) {
const out = {};
for (let [key, value] of Object.entries(obj)) {
if (value && args.includes(key)) {
out[key] = value;
};
}
return out;
}
console.log(denormalizeUserData(userData));
console.log(denormalizeUserData(userData, 'avatar', 'name'));
console.log(denormalizeUserData(userData, 'avatar', 'name', 'celebrity'));

Pass value and use as object properties dynamically in Javascript

Is there a way I can pass a parameter value into a function and use it as properties of an object?
const state = {
name: 'xyz',
properties: 'abc'
}
...
const handleStuff = (properties:string) => {
const a = [...state.properties]
if (action.status == true)
{
//some code
return {
...state,
properties: a
}
} else {
//some code
return {
...state,
properties: a
}
}
}
It is still not clear what result you are trying to reach, but generally you can access your properties by [] operator.
if you want just to store state.name value into variable you should do following
const a = state[properties] // a will be 'xyz'
code below will be evaluated as spread operation performed on the string 'xyz'
const a = [...state[properties]] // a will be equal to ['x', 'y', 'z']
in your return statement, where you want to combine object and if you want to assign value to property with name properties (which is 'name' for example) you can
return {
...state,
[properties]: a // name value from the state will be overridden with value of variable a
};

destructing nested object in react prop got error

const {
user: { name }
} = props;
With the above code, I got
name of undefined when the user object is undefined
I like destructing but should it be used this way? The issue is there's no fallback to crash my react app. I rather do destruct and use ? as a fallback:
const {
user
} = props;
return <div>user?.name</div>
Try this instead:
const {
user: { name = '' } = {name: ''}
} = props;
<div>{name}</div>
In case that the property you are destructuring is not defined,
You can assign "Default values" like this:
const props = {diffUser: {name: "Peter"}};
const { user: {name} = {name: "default-value"} } = props;
console.log(name);
The simpler example,
var { message: msg = "Something went wrong" } = {};
console.log(msg);
A variable can be assigned a default, in the case that the value unpacked from the object is undefined.
You can just add a quick default value an check for undefined or null string after:
const { user: { name } = {} } = props;
This way it will not throw an error if 'user' is undefined, name will just be undefined also.

How can I access a nested object inside an array to validate it?

This is my schema:
detail: [{
quantity: Number,
product:{
name: String,
code: Number,
price: Number
},
subtotal: Number
]}
This is my validations method
const validations = values => {
const errors = {
product: {}
}
if(!values.detail ||
!values.detail.length){
errors.detail = {_error: 'at
least one item must be
required'}
}
else{
const detailArrayErrors = []
values.detail.forEach(
(item,itemIndex) =>{
const detailErrors = {}
if(!item || !item.quantity){
detailErrors.quantity
='Required'
detailArrayErrors[itemIndex]=
detailErrors
}
if(!item || !item.subtotal){
detailErrors.subtotal
= 'required'
detailArrayErrors[itemIndex]
= detailErrors
}
//How can I access product
// in validations method
})
if(detailArrayErrors.length)
errors.detail =
detailArrayErrors
}
return errors;
}
export default validations;
product is my nested json object inside detail. Detail is an array. I want to validate product. How can I access a nested json object inside an array for validate it?
I've tried using for... of, but it makes not results.
I was searching on web but I couldn't find nothing.
How can I do that?
Anyone who knows?
values.detail.forEach(d=> console.log(d.product));
To get array of invalid e.g.:
let invalidItems = values.detail.filter(d => !d.product || !d.quantity ||
!d.product.name);
To do something on each item in array:
this.values.detail.forEach(i =>
{
let detailErrors = {'quantity': null, product: null};
if (!i.quantity)
{
detailErrors.quantity= 'Required'
}
if (!i.product)
{
detailErrors.product = 'Required'
}
if (i.product && !i.product.price)
{
detailErrors.product = {'price' :'Required'}
}
});

Destructuring without "Uncaught ReferenceError: props is not defined"

I'm trying to find something about destructuring :
If I do something like this :
const { id, category: { categoryId } } = {};
It throws an error
VM136:1 Uncaught TypeError: Cannot destructure property "categoryId" of "undefined" or "null".
because we are trying to access props categoryId of category, but category is undefined.
Is there any solution to do this only on one line destructuring ? I tried :
const { id, category: { categoryId = null } = {} } = {};
OR
const { id, category: { categoryId } = { categoryId = null } = {};
But it does not works.
I can easily do that with :
const { id, category } = {};
let categoryId = null;
if (category) ({ categoryId } = category);
thanks all !
You can hav an IIFE that returns the destructed properties and add a check for category in it :
const obj = {
id: 5,
category: null
};
const {
id,
category: { categoryId }
} = (({ id, category }) => ({ id, category: category || {} }))(obj);
console.log(id, categoryId);
you must have categoryId on right side (in your props)
const { id, category: { categoryId } } = {id: 0, category: {categoryId: 0}}
or
const props = {id: 0, category: {categoryId: 0}} // your props have to look like this
const { id, category: { categoryId } } = props;
Unfortunately there's no syntax to allow you to optionally destructure if something exists, you have to first check that the thing you want to destructure exists.
There's a proposal for optional chaining and some discussion around how that might affect destructuring, but that's not going to help you in the short-term.
In the meantime, you could look at lodash get which prevents the error you're seeing being thrown and also allows you to also provide default values for when something doesn't exist.
If category is undefined the you cannot get categoryId.
const { id, category: { categoryId } } = { category: { categoryId: 1 } };
console.log(categoryId)
Yes you can with the default value
var { id, category: { categoryId } = {categoryId: 'some'}} = {}
console.log(categoryId)
// When you set a default value for categoryId to it will always get that default value
// in case the destrucutured value is undefined
var { id, category: { categoryId = null } = {}} = {};
console.log(categoryId)
To understand this you can transpile this to ES5 using babel
"use strict";
var _ref = {},
id = _ref.id,
_ref$category = _ref.category;
_ref$category = _ref$category === void 0 ? { categoryId: 'some' } : _ref$category;
var categoryId = _ref$category.categoryId;
console.log(categoryId);
You can clearly understand from this simplified code how destructuring works under the hood
check for the value from the object at the right side, if the value is found, ignore default value if there's any
If the value is not found or it is undefined, check for the default value if there's any else keep it as it is,
In the context of this example, if you see the id and category aren't found on object, so the value of them is undefined, but here we have a default value for the category so it uses than value to get value of category, which will be { categoryId : 'some' }. now when you de-structure category further you're actually destructuring {categoryId: 'some'}, so final value of categoryId will be some
in this example
var { id, category: { categoryId = null } = {}} = {};
value of category will be undefined so when you further proceed to get value of categoryId it checks value of category since it is undefined it uses null as default value

Categories

Resources