Get array from a multidimensional object - javascript

I'm trying to grab the classes array based an id from the object. (and store it)
const objs = {
"1":{
"name":"Candice",
"classes": [00029,00023,00032,000222],
"id":0002918
},
"2":{
"name":"Clark",
"classes":[000219,00029,00219],
"id":00032
}
}
const objsKeys = Object.keys(objs);
const userClasses = objKeys.find(a => objs[a].id === this.state.userId).classes
console.log(userClasses);
// expect output
[00029,00023,00032,000222]
// but returns
Uncaught TypeError: Cannot read property 'classes' of undefined
What am I doing wrong here? Thank you for your help in advance!

You are getting the property name using Array#find method, and you are trying to get classes property of string and which is undefined . So you need to get the property value from object using the property name returned by Array#find method.
const userClasses = objs[objKeys.find(a => objs[a].id === this.state.userId)].classes

You are only getting the key.
Try:
const objs = {
"1":{
"name":"Candice",
"classes": [00029,00023,00032,000222],
"id":0002918
},
"2":{
"name":"Clark",
"classes":[000219,00029,00219],
"id":00032
}
}
const objsKeys = Object.keys(objs);
//if you console.log the following, you get the property/key of 2:
console.log(objsKeys.find(a => objs[a].id === 00032))
// you need to use that property to get the object value
const userClasses = objs[objsKeys.find(a => objs[a].id === this.state.userId)].classes
console.log(userClasses);

Related

How do I get only the value of an object?

I use TypeScript.
I want to get only the value of an object, but this error occurs: “TypeError: Cannot read properties of undefined (reading 'cd1')”.
callList = {
cd1: "00001",
nm1: "17"
}
// cd = '17'
const getFindbyNm(cd) => {
const idx = callList.find(e => e.nm1 == cd)
console.log(idx['cd1']); // ← Error occuered.
}
What am I doing wrong?
Your code isn't properly structured, it's not really valid JS even.
With some code cleaning, it works, but as some have stated, you need to use an Array for .find() to work.
const callList = {
cd1: "00001",
nm1: "17"
};
const cd = '17';
const getFindbyNm = (param1, param2) => {
return param1.find(e => e.nm1 == param2);
};
console.log(getFindbyNm([callList], cd));
console.log(getFindbyNm([callList], cd).cd1);
Considering callList is an Array
const callList =
[{
cd1: "00001",
nm1: "17"
}]
Array.prototype.find returns an array item or undefined, as an item may not be found within the given array. This is why idx may be undefined, hence cd1 may not exist on undefined
To fix it you can either check if idx isn't undefined
if(idx){
console.log(idx['cd1']);
}
or use the optional chaining operator ?.
console.log(idx?.['cd1'])
TS Playground
you can use Object.entries instead of find since find is function in array not in object. Object.entries has the attributes of both the key and the value
const callList = {
cd1: "00001",
nm1: "17",
};
const getFindByNm = (cd) => {
let returnval;
Object.entries(callList).forEach(([key, value]) => {
if (key == 'nm1' && value == cd) {
returnval = value;
}
});
return returnval;
};
let val = getFindByNm("17");
console.log(val);

parse value from array of object: error undefined is not iterable

I would like to get the value from array under of object and also provide some error checking. I have following code to check if key exist and if value of key is array type or not. if yes, I would like to get the value from the key. it seems ok, but any better way I can get value? I tried to use const [value] = obj?.the_key but get exception Uncaught TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator)) if
value from the_key is not array or the_key does not exist under object
const obj = {'theKey': ['correct value']}
const hasKey = obj['theKey'] !== undefined && Array.isArray(obj.theKey)
if (!hasKey) console.log('null')
const [value] = obj.theKey
console.log(value)
You can use the hasOwnProperty and isArray functions to check if your object has the key / property that you are looking for.
const obj = { 'theKey' : ['correct value'] };
let hasKey = obj.hasOwnProperty('theKey'); // This will return true / false
if (!hasKey) { // key does not exist
// error handling logic
}
Then you can check the data type of the value if it is array or not
if (hasKey) {
let keyVal = obj.theKey;
if (Array.isArray(keyVal)) { // returns true or false
// business logic with array
} else { // key value is not array
// error handling
}
}

React: Properties change to undefined after updating a property in an array of objects

What I was trying to do is just updating a property in an object in an array and update the array state.
But all the properties change to undefined except for the one that has been updated after updating the object.
Code is like below.
let copyOfItems = [...items];
console.log(copyOfItems[currentIndex].propertyA); // a Value
const updatedItem = {
...copyOfItems[currentIndex],
propertyB: "newVal"
};
console.log(updatedItem.propertyA); // undefined
console.log(updatedItem.propertyB); // newVal
copyOfItems[currentIndex] = updatedItem;
setItems(copyOfItems);
What is wrong with this?
Why not try it this way to see how it works?
let copyOfItems = [...items];
console.log(copyOfItems[currentIndex].propertyA); // a Value
copyOfItems[currentIndex]['propertyB'] = 'new val'; // yes this is valid
console.log(copyOfItems[currentIndex].propertyA); // this should not be undefined
console.log(copyOfItems[currentIndex].propertyB); // newVal
setItems(copyOfItems);

What does the question mark mean in the return statement in JS?

I've got a function service the using data from loader and transform it in the right way for me and then return new data
I have a suggestion to use '?' before returning data in transformation that can make some sense if there will not be data from loader:
export default async function serviceInputSearch(url) {
const data = await new DataLoader(url).get();
return data?.data.results;
}
I cannot find any information in google about this '?' in return statement?
What does it mean?
This is called optional chaining. You can find more information about it here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining.
But, given your example, the gist of it is that the question mark validates if there is a valid "data" object. If you do not have the question mark there and there is no data object or it is null, then an error will be thrown in the lines of "Cannot read the property data of 'undefined'".
Its the "optional chainging" operator.
Here an use case:
let obj = {};
console.log(obj?.person?.age);
console.log(obj.person.age);
It comes handy if you try to access an property that not there. Its undefined so you get the error cannot get xx of undefined
To prevent this error you put an ?. infront of it, it will return an undefined back rather then throwing an error
Here some examples:
let obj = {};
//method does not exist
console.log(obj.func?.())
let arr = ["tom"];
console.log(arr[2]?.name);
let matrix = [ [ 1 ], [ 2 ] ];
console.log(matrix[5]?.[3]);
let defaultName = obj?.name ?? "Tom";
console.log(defaultName);
This is called as Optional chaining
const adventurer = {
name: 'Alice',
cat: {
name: 'Dinah'
}
};
// you can use it to check if the property is exist in the object
const dogName = adventurer.dog?.name; //same as adventurer.dog && adventurer.dog.name ? adventurer.dog.name : undefined;
console.log(dogName); //undefined
or else you can use it for check/call the existence of function of inside a object
// if someNonExistentMethod is exists in the adventurer Object call it.
console.log(adventurer.someNonExistentMethod?.());
Syntax is
const adventurer = {
name: 'Alice',
cat: {
name: 'Dinah'
},
skills: ['jump']
};
obj.val?.prop => //Optional chaining
ex: adventurer.dog?.name
obj.val?.[expr] => //Optional chaining with expressions
ex: const propertyName = 'name'; adventurer.dog?.[propertyName];
obj.arr?.[index] => //Array item access with optional chaining
ex: adventurer.skills?.[0] //jump
obj.func?.(args) => //Optional chaining with function calls
ex: adventurer.someNonExistentMethod?.()
It is optional chaining operator.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining
reference
In Javascript, we would need to explicitly check every reference to make sure it’s defined. If we have a deeply nested reference within an object, it might look something like this:
let networkFetchResult = await fetch("https://myfriends.com/user/123").then(res => res.json());
// Let's assume that the first friend of our request user is our best friend
let bestFriendsName = networkFetchResult
&& networkFetchResult.data
&& networkFetchResult.data.user
&& networkFetchResult.data.user.friends
&& networkFetchResult.data.user.friends[0]
&& networkFetchResult.data.user.friends[0].name
|| "You don't have any friends!";
Instead you can just do
let networkFetchResult = await fetch("https://myfriends.com/user/123").then(res => res.json());
// Still assuming that our first friend is our best friend
let bestFriendsName = networkFetchResult?.data?.user?.friends?.[0]?.name || "You don't have any friends!";

Read variable number of properties from object

Say I have this function signature:
export const readVariableProps = function(obj: Object, props: Array<string>) : any {
// props => ['a','b','c']
return obj['a']['b']['c'];
}
obviously, props is a variable length array, with an unknown list or properties to read from the given object.
is the only way to get this kind of dynamic behavior to use eval()?
How can I do this?
To get the equivalent of return obj['a']['b']['c']; where 'a', 'b' and 'c' are the values in the array like you show in your question, you can do something like this (you may have to convert some details to typeScript):
export const readVariableProps = function(obj: Object, props: Array<string>) : any {
return props.reduce(function(prior, next) {
return prior[next];
}, obj);
}
FYI, this type of scenario is exactly what .reduce() was designed for -
accumulating a value that is built by visiting every item in an array.
This will throw if anything other than the last property in the array does not exist.
You can use a for..of loop to set a variable to each nested property
const props = ['a','b','c'];
const obj = {a:{b:{c:123}}};
let res;
for (let prop of props) res = !res ? obj[prop] : res[prop];
console.log(res);

Categories