Updating an object with setState in React (solidity event filter) - javascript

Is it at all possible to update the object's properties with setState?
Something like:
this.state = {
audit: { name: "1", age: 1 },
}
I can log the event to the console using:-
myContract.once('MyEvent', {
filter: {myIndexedParam: [20,23], myOtherIndexedParam: '0x123456789...'}, // Using an array means OR: e.g. 20 or 23
fromBlock: 0
}, function(error, event){ console.log(event); });
my solidity ABI object created on console is
App.js:42
{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 setState the required data and use it later so I am using .setState like this
showusingID(ids){
this.setState({ loading: true })
this.state.instance.events.Artworkcreated({
filter: { id: ids},
fromBlock: 0,
}).on('data', function(event){
this.setState({...this.state.audit, name: 'someothername'});
})
}
but it showing
.setState is not a function.

Use arrow function in on('data').
showusingID = ids => {
this.setState({ loading: true })
this.state.instance.events.Artworkcreated({
filter: { id: ids},
fromBlock: 0,
}).on('data', event => {
this.setState({...this.state.audit, name: 'someothername'});
})
}

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);

How to access 0th index of array 'favorite foods' in this nested objects?

I try to access to 0th index of the array in my following object:
let spaceship = {
passengers: null,
telescope: {
yearBuilt: 2018,
model: "91031-XLT",
focalLength: 2032
},
crew: {
captain: {
name: 'Sandra',
degree: 'Computer Engineering',
encourageTeam() {
console.log('We got this!')
},
'favorite foods': ['cookies', 'cakes', 'candy', 'spinach']
}
},
engine: {
model: "Nimbus2000"
},
nanoelectronics: {
computer: {
terabytes: 100,
monitors: "HD"
},
'back-up': {
battery: "Lithium",
terabytes: 50
}
}
};
I tried following code:
let capFave=spaceship.crew.captain['favorite foods']['favorite foods[0]'];
and
let capFave=spaceship.crew.captain['favorite foods[0]'];
but it returns undefined or shows syntax error.
Just use [0] after spaceship.crew.captain['favorite foods'], like spaceship.crew.captain['favorite foods'][0], since spaceship.crew.captain['favorite foods'] returns an array, and [0] returns the value in the 0th index of an array.
let spaceship = {
passengers: null,
telescope: {
yearBuilt: 2018,
model: "91031-XLT",
focalLength: 2032
},
crew: {
captain: {
name: 'Sandra',
degree: 'Computer Engineering',
encourageTeam() { console.log('We got this!') },
'favorite foods': ['cookies', 'cakes', 'candy', 'spinach']
}
},
engine: {
model: "Nimbus2000"
},
nanoelectronics: {
computer: {
terabytes: 100,
monitors: "HD"
},
'back-up': {
battery: "Lithium",
terabytes: 50
}
}
};
console.log(spaceship.crew.captain['favorite foods']);
console.log(spaceship.crew.captain['favorite foods'][0]);

react TypeError: Cannot read property 'type1' of undefined

I'm studying the react-beautiful-dnd example, and I want to add a conditional repulsion of an element, but I get an error that the field cannot be read.
This data
const initialData = {
tasks: {
'task-1': { id: 'task-1', content: 'Take out the garbage',type1: 'w' },
'task-2': { id: 'task-2', content: 'Watch my favorite show',type1: 'a' },
'task-3': { id: 'task-3', content: 'Charge my phone',type1: 'h' },
'task-4': { id: 'task-4', content: 'Cook dinner',type1: 'w' }
},
columns: {
'column-1': {
id: 'column-1',
title: 'To do',
type2: 'all',
taskIds: ['task-1', 'task-2', 'task-3', 'task-4']
},
'column-2': {
id: 'column-2',
title: 'In progress',
type2: 'w',
taskIds: []
},
'column-3': {
id: 'column-3',
title: 'Done',
type2: 'a',
taskIds: []
}
},
// Facilitate reordering of the columns
columnOrder: ['column-1', 'column-2', 'column-3'] }export default initialData
so they are connected
import initialData from './initial-data'
so it is assigned in state
state = initialData
this is how it is used and everything that I described it works and this is the code from the example
const start = this.state.columns[source.droppableId]
const finish = this.state.columns[destination.droppableId]
if (start === finish) {
const newTaskIds = Array.from(start.taskIds)
now below i want to add my condition and it throws an error
const typeDrag = this.state.tasks[source.draggableId]
const typeDrop = this.state.columns[destination.droppableId]
if(typeDrag.type1!==typeDrop.type2)
{return}
and I don't understand why start.taskIds works, but typeDrag.type1 reports that there is no such field
similarly executable codesandbox example
example
Solution:
instead of: const typeDrag = this.state.tasks[source.draggableId]
use: const typeDrag = this.state.tasks[draggableId]
Explanation:
In your code source doesn't have property draggableId.
So typeDrag is undefined because source.draggableId is undefined.
Argument of your onDragEnd hook looks like that:
{
"draggableId": "task-2",
"type": "TASK",
"source": {
"index": 1,
"droppableId": "column-1"
},
"destination": {
"droppableId": "column-2",
"index": 0
},
"reason": "DROP"
}
By checking your sandbox sample I see that you've already extracted draggableId property to a constant from the method argument ("result"):
const { destination, source, draggableId } = result; // line:28
So using draggableId instead of source.draggableId resolves TypeError: Cannot read property 'type1' of undefined.

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.

mapping items and flattening into single array in reactjs

Currently I have a reactjs function that simply queries a pouchDB document, gets 7 records and then I'm trying to flatten those records in order to store in state. The problem is that, right now when I console.log docCalories I get this:
(7) [{…}, {…}, {…}, {…}, {…}, {…}, {…}]
0: {caloriesBurned: "5345", createdAt: "2020-03-28T05:15:24.369Z"}
1: {caloriesBurned: "1234", createdAt: "2020-03-28T10:39:16.901Z"}
2: {caloriesBurned: "1122", createdAt: "2020-03-28T10:32:03.100Z"}
3: {caloriesBurned: "1234", createdAt: "2020-03-28T05:16:54.846Z"}
4: {caloriesBurned: "1234", createdAt: "2020-03-28T10:21:31.092Z"}
5: {caloriesBurned: "1234", createdAt: "2020-03-28T05:08:00.791Z"}
6: {caloriesBurned: "1234", createdAt: "2020-03-28T05:07:35.940Z"}
length: 7__proto__: Array(0)
but I want to get something that looks like this:
map: [5345,1234,1122,1234,1234,1234,1234]
So basically one object that contains the 7 numbers from each doc's caloriesBurned value
What am I doing wrong here and how can I properly put these into one array/object?
setMax = () => {
this.state.caloriesDB.db.find({
selector: {
$and: [
{_id: {"$gte": null}},
{caloriesBurned: {$exists: true}},
{createdAt: {$exists: true}}
]
},
fields: ['caloriesBurned', 'createdAt'],
sort: [{'_id':'desc'}],
limit: 7
}).then(result => {
const newDocs = result.docs;
const docCalories = newDocs.map((caloriesBurned) => caloriesBurned)
console.log('this is map');
console.log(docCalories);
}).catch((err) =>{
console.log(err);
});
}
You're returning the entire object in your map function, instead you should only send the caloriesBurned property.
const docCalories = newDocs.map((data) => data.caloriesBurned)
or if you like, we can destructrure data and have
const docCalories = newDocs.map(({caloriesBurned}) => caloriesBurned)
What Dupocas has written in the comments is correct.
newDocs is a list of objects and with this code:
const docCalories = newDocs.map((caloriesBurned) => caloriesBurned)
you will just get another list that is just like newDocs. What you want to return from the map function is a specific key, so try:
const docCalories = newDocs.map(doc => doc.caloriesBurned)
considering docCalories value in m2 by creating map, you can do something like this -
const m2 = new Map(Object.entries([{
0: {
caloriesBurned: "5345",
createdAt: "2020-03-28T05:15:24.369Z"
}
},
{
1: {
caloriesBurned: "1234",
createdAt: "2020-03-28T10:39:16.901Z"
}
},
{
2: {
caloriesBurned: "1122",
createdAt: "2020-03-28T10:32:03.100Z"
}
},
{
3: {
caloriesBurned: "1234",
createdAt: "2020-03-28T05:16:54.846Z"
}
},
{
4: {
caloriesBurned: "1234",
createdAt: "2020-03-28T10:21:31.092Z"
}
},
{
5: {
caloriesBurned: "1234",
createdAt: "2020-03-28T05:08:00.791Z"
}
},
{
6: {
caloriesBurned: "1234",
createdAt: "2020-03-28T05:07:35.940Z"
}
}
]))
var store = [];
Array.from(m2).map(([key, value]) => store.push(value[key].caloriesBurned));
console.log(store);

Categories

Resources