ReactJS Convert my strange array to an object to add it to a list - javascript

I have the following array:
[{…}]
0: {id: 2, createdAt: "2021-06-11T10:13:46.814Z", exchangedAt: "2021-06-11T08:04:11.415Z", imageUrl: "url", user: "user", …}
1: ....
2: ....
3: ....
....
length: 5
__proto__: Array(0)
I want to convert it to an object and I found this code, but all I receive is the 0:
Object.keys(fetchedData.data).map(key => console.log(key))
How to access and convert my 5 array values?

So I've iterated across your array and used the 'id' field as a key. The key for each object needs to be unique, so this assumes your ID is unique...
const fetchedData = [
{id: 1, createdAt: "2021-06-11T10:13:46.814Z", exchangedAt: "2021-06-11T08:04:11.415Z", imageUrl: "url", user: "user"},
{id: 2, createdAt: "2021-06-11T10:13:46.814Z", exchangedAt: "2021-06-11T08:04:11.415Z", imageUrl: "url", user: "user"},
{id: 3, createdAt: "2021-06-11T10:13:46.814Z", exchangedAt: "2021-06-11T08:04:11.415Z", imageUrl: "url", user: "user"}
]
obj = {}
fetchedData.forEach(x => {
tempX = {...x}
delete tempX["id"]
obj[x.id] = tempX
})
console.log('Converted object', obj)
//Using your method, just to log the values without converting it into an object, you could do...
fetchedData.forEach(el => console.log("Individual Element", el))
...so when you use Object.keys() you are iterating across the keys of an object, but as this is an array of objects, the keys are just the indexes of the array. .forEach iterates across the array and gives you each element to work with.
You've used .map() in your code, which also iterates through an array, but returns a new array, so you could change each element. .forEach just iterates and doesn't return, so you're better off using this for logging to the console.

a = [
{
"id":1,
"createdAt":"2021-06-11T10:13:46.814Z",
"exchangedAt":"2021-06-11T08:04:11.415Z",
"imageUrl":"url",
"user":"user"
},
{
"id":2,
"createdAt":"2021-06-11T10:13:46.814Z",
"exchangedAt":"2021-06-11T08:04:11.415Z",
"imageUrl":"url",
"user":"user"
},
{
"id":3,
"createdAt":"2021-06-11T10:13:46.814Z",
"exchangedAt":"2021-06-11T08:04:11.415Z",
"imageUrl":"url",
"user":"user"
},
{
"id":2,
"createdAt":"2021-06-11T10:13:46.814Z",
"exchangedAt":"2021-06-11T08:04:11.415Z",
"imageUrl":"url",
"user":"user"
},
{
"id":4,
"createdAt":"2021-06-11T10:13:46.814Z",
"exchangedAt":"2021-06-11T08:04:11.415Z",
"imageUrl":"url",
"user":"user"
}
]
(5) [{…}, {…}, {…}, {…}, {…}]
Object.keys(a).map(key => console.log(key))
VM532:1 0
VM532:1 1
VM532:1 2
VM532:1 3
VM532:1 4
It is accessing to 5 values.

Related

Javascript extracting values from deeply nested array object structure

I'm trying to pull out specific fields from backend data to prep the body of a table. The data coming in has the structure of:
[
{
_id: "63056cee252b83f4bc8f97e9",
goals: [
{ title: "Cook" },
{ title: "Budget" }
],
visitEnd: "2022-08-18T00:30:00.000Z",
visitStart: "2022-08-17T21:30:00.000Z",
},
{
_id: "63223586798c6b2658a0d576",
goals: [
{ title: "Cook" },
{ title: "Budget" },
{ title: "Clean" }
],
visitEnd: "2022-09-13T00:30:00.000Z",
visitStart: "2022-09-12T22:00:00.000Z"
},
{
_id: "63542ecfca5bd097a0d9acaf",
goals: [
{ title: "Cook" },
{ title: "Clean" }
],
visitEnd: "2022-10-12T19:00:11.000Z",
visitStart: "2022-10-12T17:00:00.000Z",
}]
Since the table headers are by month/year, I'm using lodash to group them by month, which gets me here:
Object { 7: (2) […], 8: (2) […], 9: (2) […] }
​
7: Array [ {…}, {…} ]
​​
0: Object { user: "62410a1dcaac9a3d0528de7a", location: "Firm Office in LA", visitStart: "2022-08-17T21:30:00.000Z", … }
​​
1: Object { user: "62410a1dcaac9a3d0528de7a", location: "place", visitStart: "2022-08-11T21:00:57.000Z", … }
​​
length: 2
​​
<prototype>: Array []
​
8: Array [ {…}, {…} ]
​​
0: Object { user: "62410a1dcaac9a3d0528de7a", location: "Home", visitStart: "2022-09-12T22:00:00.000Z", … }
​​
1: Object { user: "62410a1dcaac9a3d0528de7a", location: "place", visitStart: "2022-09-21T21:00:00.000Z", … }
​​
length: 2
​​
<prototype>: Array []
​
9: Array [ {…}, {…} ]
​​
0: Object { user: "62410a1dcaac9a3d0528de7a", location: "Home", visitStart: "2022-10-12T17:00:00.000Z", … }
​​
1: Object { user: "62410a1dcaac9a3d0528de7a", location: "place", visitStart: "2022-10-21T21:00:00.000Z", … }
​​
length: 2
But now I'm stuck since I want to isolate the fields of the goals array, which is within the objects, within the array of each month, which is contained in an object. I've tried playing around with Object.keys and maps, and then from here: https://dev.to/flexdinesh/accessing-nested-objects-in-javascript--9m4 came across a function to get deeply nested items. But I'm still messing this up, and my head is spinning trying to make sense of it. I looked at lodash's map and property, but was not sure how to implement given the layers of nesting I'm trying to work through on dynamically named arrays within the groupBy object. Heres where I'm at, but I'm getting the error i.map is not a function
const sort = groupBy(visits, ({visitEnd})=> new Date(visitEnd).getMonth());
console.log("sort 1: ", sort)
const stage = Object.keys(sort).map((i) => {
{ i.map((el) => getNestedObject(el, ['goals', 'title'])) }
})
console.log("sort 2: ", stage)
My javascript knowledge is terrible which doesn't help...
The error you're getting, i.map is not a function, means that the variable i is not an array. Based on the data you supplied in your post i is an object.
Iterate the result of the sorted month/year data using Object.entries() versus Object.keys().
To get a list of unique goals per month with output that looks like:
{
7: ["Cook", "Spend", "Clean"],
8: ["Cook", "Budget", "Clean"],
9: ["Cook", "Budget", "Scrub", "Fold", "Rest", "Wash"]
}
const dataSortedByMoYrObj = {
7: [
{
user: "62410a1dcaac9a3d0528de7a", location: "Firm Office in LA", visitStart: "2022-08-17T21:30:00.000Z",
goals: [
{ title: "Cook" },
{ title: "Spend" },
{ title: "Clean" }
]
},
{
user: "62410a1dcaac9a3d0528de7a", location: "place", visitStart: "2022-08-11T21:00:57.000Z",
goals: [
{ title: "Cook" },
{ title: "Clean" }
]
}
],
8: [
{
user: "62410a1dcaac9a3d0528de7a", location: "Home", visitStart: "2022-09-12T22:00:00.000Z",
goals: [
{ title: "Cook" },
{ title: "Budget" },
{ title: "Clean" }
]
},
{ user: "62410a1dcaac9a3d0528de7a", location: "place", visitStart: "2022-09-21T21:00:00.000Z" }
],
9: [
{
user: "62410a1dcaac9a3d0528de7a", location: "Home", visitStart: "2022-10-12T17:00:00.000Z",
goals: [
{ title: "Cook" },
{ title: "Budget" },
{ title: "Scrub" }
]
},
{
user: "62410a1dcaac9a3d0528de7a", location: "place", visitStart: "2022-10-21T21:00:00.000Z",
goals: [
{ title: "Fold" },
{ title: "Rest" },
{ title: "Wash" }
]
}
]
};
// 'const getNestedObject' code sourced from:
// https://dev.to/flexdinesh/accessing-nested-objects-in-javascript--9m4
const getNestedObject = (nestedObj, pathArr) => {
return pathArr.reduce((obj, key) =>
(obj && obj[key] !== 'undefined') ? obj[key] : undefined, nestedObj);
}
const goalsByMonthYearObj = {};
Object.entries(dataSortedByMoYrObj).forEach(([month, users]) => {
// 'month' represents the key.
// 'users' is an array of objects listed for each month.
let goalsByMonth = [];
users.map(user => {
const goalsProp = getNestedObject(user, ['goals']);
// Check if the 'goals' property is a valid.
// If 'goals' property is 'null' or 'undefined',
// '!Array.isArray(null)' returns 'true'.
if (!Array.isArray(goalsProp)) { return; }
// Convert list of goal objects (e.g. '{title: Budget}')
// to an array using 'goalsProp.map()' and then
// concatenate goals array to the existing
// goals-by-month array.
goalsByMonth = goalsByMonth.concat(goalsProp.map(goal => goal.title));
});
// Add array of unique goals for each month
// https://stackoverflow.com/questions/1960473/get-all-unique-values-in-a-javascript-array-remove-duplicates
goalsByMonthYearObj[month] = [...new Set(goalsByMonth)];
});
console.log(goalsByMonthYearObj);
(Original code that's not as concise as above snippet.)
const goalsByMonthYearObj = {};
// Reference to 'Object.entries()' at:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries
for (const [key, value] of Object.entries(dataSortedByMoYrObj)) {
// 'key' represents a month index.
// 'value' contains an array of objects listed for each month index.
//console.log(`${key}: ${value}`);
const goalsByMonth = [];
value.forEach(item => {
// The 'goals' property is only one level deep so
// it's not necessary to use the 'getNestedObject()'
// function.
// For example: const goalsProp = item.goals;
// The function is useful for more deeply
// embedded properties.
const goalsProp = getNestedObject(item, ['goals']);
if (!Array.isArray(goalsProp)) { return; }
goalsProp.forEach(goal => {
if (!goal.title) { return; }
goalsByMonth.push(goal.title);
});
});
// https://stackoverflow.com/questions/1960473/get-all-unique-values-in-a-javascript-array-remove-duplicates
const uniqueGoals = [...new Set(goalsByMonth)];
goalsByMonthYearObj[key] = uniqueGoals;
}
console.log(goalsByMonthYearObj);

TypeError: Cannot read property 'map' of undefined but state has been stored

I am trying to get a specific team data from the database and store it in a state. But when I map an array inside that data it returns an error. When I console log my state it returns the data below
createdAt: "2021-03-19T13:36:22.868Z"
gameEvent: "basketball"
players: Array(5)
0: {_id: "605ea59c5cdf492b48987107", name: "Jerry Ale", jerseyNumber: "12"}
1: {_id: "605ea59c5cdf492b48987108", name: "Judel Agur", jerseyNumber: "14"}
2: {_id: "605ea59c5cdf492b48987109", name: "qwe", jerseyNumber: "12"}
3: {_id: "605ea59c5cdf492b4898710a", name: "qwe", jerseyNumber: "12"}
4: {_id: "605ea59c5cdf492b4898710b", name: "qwe", jerseyNumber: "12"}
length: 5
__proto__: Array(0)
teamName: "Balilihan"
updatedAt: "2021-03-27T03:25:16.148Z"
__v: 0
_id: "6054a8d63fec5c24389624ac"
I have an useEffect to gather this;
useEffect(() => {
const getTeam = async () => {
try {
const { data } = await fetchContext.authAxios.get('get-all-teams');
setIsLoaded(true);
if (isLoaded === true) {
setCurrentTeam(data.find((team) => team._id === row._id));
}
} catch (err) {
console.log(err);
}
};
getTeam();
}, [fetchContext, row, isLoaded]);
and I map the players array in a new variable because I want a controlled inputs for my form because I am updating the data. I am using Formik by the way
let playersOfTeam = currentTeam.players.map((player, index) => [
{
name: player.name,
jerseyNumber: player.jerseyNumber,
},
]);
But when I just get a specific value like the teamName it returns the teamName and when I console log currentTeam.players it returns what I expected to get. I am confused why I get this kind of error
Your data is undefined when the component is first mounted. This is because useEffect runs after render.
So adding a null check is the solution. Personally I prefer optional chaining. Simply change to:
let playersOfTeam = currentTeam?.players?.map((player, index) => [
{
name: player.name,
jerseyNumber: player.jerseyNumber,
},
]);

Filtering in Object of Arrays in Javascript

I am trying to filter out an Object of Arrays wherein I have to filter out the 'designation' 'options' of a key.
My row Object looks like.
{id: 1, columns: Array(5)}
columns: (5) [InputDate, InputSelect, InputSelect, InputSelect, InputString]
id: 1
__proto__: Object
One of the columns Array where data is looks like this.
InputSelect
name: "designation"
options: Array(3)
0: {name: "Entry", value: "ENTRY"}
1: {name: "Mid", value: "MID"}
2: {name: "Experienced", value: "EXPERIENCE"}
length: 3
__proto__: Array(0)
Now I have to search inside the columns Arrays and filter out the options of "ENTRY" if the Arrays name property is 'designation' so as to return the updated Object having this filtered value.
What I am trying now is
row.columns.map( key => {
if (key.name === 'designation') {
key.options.filter( r => r.value === "ENTRY" )
}
But it doesn't seem to be updating the row Object.
This should solve your problem.
row.columns.filter(x=>x.name=="designation").map(i=>i.options.filter(z=>z.name==="Entry"));

TypeError: prevState.blockHash is not iterable

I was trying to update the objects stored in an array. but getting TypeError: prevState.blockHash is not iterable.
here is my constructor
constructor(props) {
super(props)
this.state = {
dir:"",
account: '',
name: [],
fido: [{
logIndex: [],
transactionIndex: [],
transactionHash: [],
blockHash: []
}],
loading: true
}
I am setting state in this manner-
showusingBot= () => {
this.setState(this.initialState)
this.state.instance.events.Artworkcreated({
filter: { purchased: false},
fromBlock: 0
}).on('data', event => {
this.setState(prevState =>({
fido:[...prevState.fido.map({blockHash: [
...prevState.blockHash,
event.blockHash
]} )]}));
})
}
my ABI response on console is a follows.
{logIndex: 0, transactionIndex: 0, transactionHash: "0x94f6d8671988ceb8ef1da862257637a198f4afefc3aef6cf3eb992dfcafb0eb1", blockHash: "0xd26937f8535a335663c9af57335f7cc783aba0e9e376408cbb92c1b3f1b28166", blockNumber: 20, …}
logIndex: 0
transactionIndex: 0
transactionHash: "0x94f6d8671988ceb8ef1da862257637a198f4afefc3aef6cf3eb992dfcafb0eb1"
blockHash: "0xd26937f8535a335663c9af57335f7cc783aba0e9e376408cbb92c1b3f1b28166"
blockNumber: 20
address: "0x20B40e09b75a21E0B857F695dE5De92a5A5b5AD0"
type: "mined"
id: "log_0d967aac"
returnValues: Result
0: "1"
1: "bhavin"
2: "masterpiece"
3: "1000000000000000000"
4: "100"
5: "200"
6: "blah blah blah!!"
7: "0x04f78093E2a1C07BF6c4527Aaa00807d3132A1Df"
8: false
id: "1"
Artistname: "bhavin"
Artname: "masterpiece"
price: "1000000000000000000"
width: "100"
height: "200"
Description: "blah blah blah!!"
owner: "0x04f78093E2a1C07BF6c4527Aaa00807d3132A1Df"
purchased: false
__proto__: Object
event: "Artworkcreated"
signature: "0xf912339172a3b7eda9cb10ecdef181d10a74fc4411fe5d7e62f550ef3698d845"
raw: {data: "0x000000000000000000000000000000000000000000000000…16820626c6168212100000000000000000000000000000000", topics: Array(4)}
__proto__: Object
I need to push a string to the array blockHash.
Your whole fido map callback is incorrect, it's supposed to take a function, you are passing an object.
this.setState(prevState =>({
fido:[...prevState.fido.map({blockHash: [
...prevState.blockHash,
event.blockHash
]} )]}));
})
Correct syntax is map((current, index, originalArray) => {...}).
But I don't think you need to map anything, I think you just need to spread the previous state's fido array and add the new element
this.setState(prevState =>({
fido:[...prevState.fido, event.blockHash]
}));
Edit 1
Since fido is static, as you say, I suggest to instead just store its properties in an object, like you do with it currently as an element in an array.
this.state = {
dir:"",
account: '',
name: [],
fido: {
logIndex: [],
transactionIndex: [],
transactionHash: [],
blockHash: []
},
loading: true
}
Now, when updating the fido state, spread in the previous state and the blockHash array with new element
this.setState(prevState =>({
fido: {
...prevState.fido,
blockHash: [...prevState.fido.blockHash, event.blockHash]
},
}));
OFC, if you wanted/needed to keep it as-is, you need to access the element correctly
this.setState(prevState =>({
fido: [{
...prevState.fido[0],
blockHash: [...prevState.fido[0].blockHash, event.blockHash]
}],
}));
blockHash does not exist in state, it only exists in in the objects of state.fido. In your setState you need to access blockHash from each element of fido instead accessing it from the overall state.

Array.forEach() and Array.slice() together doesn't work correctly [duplicate]

This question already has answers here:
What is the most efficient way to deep clone an object in JavaScript?
(67 answers)
Closed 6 years ago.
it's supposed to Array.slice() let me to make a copy of an array, and then I can modify that copy without modifying the original array, but when I use Array.forEach() over the copy for delete some values this values also are removed from the original array. Does anybody have an idea why this happens?
Here is the code that I've used:
var originalArray = [
{ id: 1, name: 'Sales', datasources: [
{ id:1 , name: 'datasource1', fields: [] },
{ id:2 , name: 'datasource2', fields: [] },
] },
{ id: 4, name: 'Accounts', datasources: [
{ id:3 , name: 'datasource3', fields: [] },
{ id:4 , name: 'datasource4', fields: [] },
] },
{ id: 123, name: 'my datasources', datasources: [
{ id:1 , name: 'datasource1', fields: [] },
{ id:2 , name: 'datasource2', fields: [] },
{ id:3 , name: 'datasource3', fields: [] },
{ id:4 , name: 'datasource4', fields: [] },
] },
{ id: 12, name: 'shared datasources', datasources: [
{ id:13 , name: 'myshared datasource', fields: [] },
{ id:16 , name: 'hello test', fields: [] },
] },
];
var copyOfOriginalArray = originalArray.slice();
copyOfOriginalArray.forEach((folder, index) => {
folder.datasources = folder.datasources.filter((o) => { return o.name.trim().toLowerCase().includes('hello'); });
});
JSON.stringify(originalArray);
JSON.stringify(copyOfOriginalArray);
Acording to this definition.
The slice() method returns a shallow copy of a portion of an array into a new array object.
Shallow copy is a bit-wise copy of an object. A new object is created that has an exact copy of the values in the original object. If any of the fields of the object are references to other objects, just the reference addresses are copied i.e., only the memory address is copied.
for deep copying any object in javascript you can use this function:
function deepCopy(oldObj) {
var newObj = oldObj;
if (oldObj && typeof oldObj === 'object') {
newObj = Object.prototype.toString.call(oldObj) === "[object Array]" ? [] : {};
for (var i in oldObj) {
newObj[i] = deepCopy(oldObj[i]);
}
}
return newObj;
}
Slice will create a copy of the array itself, but it will not clone the objects in the array (those will still be references).
You will need to recursively clone your array and its contents or use something like Lodash's cloneDeep

Categories

Resources