How to push array of objects into state using hooks - reactjs

I have a useState as const [responses, setResponses] = useState([]);
I get the response and log it as follows :
const tempResults = res.data.data;
console.log(tempResults.length);
console.log(tempResults);
The log shows as:
When I click to open the Array of 6 items, results are .
So it is an array of objects.
I tried to set the initial value of the state as per the object
{
"index": 0,
"ds": "2020-03-06",
"yhat_lower": -10712.5597359237,
"yhat_upper": 25376.4649581317,
"yhat": 6955.3671910982,
"mape": 21.4472070205,
"rmse": 667.0969808414,
"mae": 475.3343871057,
"smape": 5.143548286
}
But when I logged, the state only had the initial value and had not appended the response array.
I am setting state as :
setResponses(...responses, tempResults);
const x = typeof responses;
console.log("TypeOfResponse", x);
console.log("RESPONSES ", responses);
However, the state of the 'responses' object as per console is this:
So it is not able to save the Array object into state. What could be wrong? Any suggestions, please?

if res.data.data is an array
then set to setResponses like this
setResponses(res.data.data)
or
setResponses([...responses, ...res.data.data])

Related

replace an array object in component state

My goal is to map over an array and replace objects that match a condition. Much like this working example:
const rows = [{
"name": "Dad",
"car": "Sedan"
}, {
"name": "Mom",
"car": "Sedan"
}]
const newCar = {
"name": "Dad",
"car": "Minivan"
}
const newArray = rows.map((r) => (r.name === newCar.name ? newCar : r))
console.log(newArray)
In my use case, component state contains the array, which is populated from an API.
const [rows, setRows] = useState([])
Later, a change is required to one object in the array. The data variable contains the modified object to be merged into the array. I map over the array looking for matches on the _id field. When the _id matches, I return the object from data (the value to be merged into the array). When there is not a match, I return the object as it originally existed in state.
setRows((rows) => [
...rows,
rows.map((r) => (r._id === data._id ? data : r)),
])
The desired outcome is an array of the same size as the original. This new array should contain one modified object in addition to all original array values.
The actual results from the code above are that the modified data object is added rather than updated.
How can I change my code to replace the modified array element instead?
The useState() functional updates form calls a function and passes it the previous state. The Array.map() function returns a new arrays with the updated values. This means that you only need to map the previous state to get a new state:
setRows(rows => rows.map((r) => (r._id === data._id ? data : r)))

Unable to understand setState of react js function paramters in a specific call?

setListOfPosts(curPosts => {
let newPosts = [...curPosts];
newPosts[newPosts.findIndex(p => p.id === postId)].alert = response.data;
}
});
//is curPosts an instance of array or complete array?? my listofPosts is an array of objects
Your setState call needs to return newPosts, and you're creating an array using the spread operator which is why it's coming back as an array of objects.
I'm not sure what your desired output is, but by adding a return function it will set the state:
setListOfPosts(curPosts => {
let newPosts = [...curPosts];
newPosts[newPosts.findIndex(p => p.id === postId)].alert = response.data;
return newPosts
}
});
This is untested but if your logic is correct should return an array of objects with the objects alert value updated.
Another option would be to do your logic before your setState call, by creating a a newState array and then simply updating the state with that new array without the use of the callback.
The callback function is useful if you want to add a new object to state array or do something that preserves the initial state, in your example you could do it without the callback like this:
// Create a copy of the state array that you can manipulate
const newPosts = [...newPosts]
if (data.response) {
// Add your logic to the state copy
newPosts[newPosts.findIndex(p => p.id === postId)].alert = response.data;
// Replace state with state copy
setListOfPosts(newPosts)
}
Again untested but hopefully this should help you understand the use of the callback function and the right way to use it.

Firestore navigation for onUpdate and shuffle an array

I have this Firebase structure:
Firebase Structure.
Then I have a function in my Code, which adds a map called "set".
My Structure is looking like this after: New structure.
Now i want an onUpdate Firebase function, which is called after the map "set" is added in any document.
This function should shuffle my "question" array.
I tried something like this:
exports.shuffleSet = functions.firestore
.document('duell/{duell_id}/set/questions')
.onUpdate((change, context) => {
const data = change.after.data();
const previousData = change.before.data();
if (data.name == previousData.name) {
return null;
}
//shuffle code here
});
But Im not sure if .document('duell/{duell_id}/set/questions') is the correct way to navigate to the question array. And at the beginning the "set" is not even existing as explained at the top.
How do I navigate to the question array correctly, that I can pull it & update it shuffled?
You should pass a document path to functions.firestore.document(). You cannot pass a field name, since Firestore Cloud Functions are triggered by documents events.
So you should do as follows:
exports.shuffleSet = functions.firestore
.document('duell/{duell_id}')
.onUpdate((change, context) => {
if (!change.after.data().shuffledSet) {
const data = change.after.data();
const question = data.set.question; // get the value of the question field
const shuffledSet = shuffle(question); // generate the new, suffled set. It’s up to you to write this function
return change.after.ref.update({shuffledSet});
} else {
return null; // Nothing to do, the shuffled field is already calculated
}
});

How can i pop a value with key from local state?

I have a local state as object:
selectedDates = {};
When i click on icons I am getting ID´s in my local state as object key, value pair.
// We "open" the value to extract the relevant informations
const [key, value] = calendarIconId.split("=");
// Add the new value inside of the object
this.state.selectedDatesTemp[key] = value;
// Turn the object into an array, we gotta rebuild the values
const date = Object.keys(this.state.selectedDatesTemp).map(
x => `${x}=${this.state.selectedDatesTemp[x]}`
);
How can i delete an object from the local state?
You can use delete to achieve it:
const { selectedDatesTemp } = this.state;
delete selectedDatesTemp[key];

Array.filter() in Angular 2 Component

In one component I can filter my array using the following:
// Array of product objects
const result = products.filter(p => p.name.includes('val'));
and value of products remains same as the first value but filtered value stores in result.
But in the following code, filter() filters array of strings itself:
// Array of strings
const result = strs.filter(s => s.includes('val'));
The question is how can I filter strings and return result without modifying the strs itself?
Note: I tried with array.filter(function() { return res; }); but didn't make any change.
It returns the filtered ones and don't change the actual array. You are doing something wrong
const strs = ['valval', 'bal', 'gal', 'dalval'];
const result = strs.filter(s => s.includes('val'));
console.log(strs);
console.log(result);
First thing we need to know is, if we filter our list we loose our original data
products: any[] = [
{
"productId": 1,
"productName": "foo-bar",
"price": 32.99
}
]
and can't get it back without re-getting the data from it's source so we have to make another list to store the filtered list.
filteredProduce: any[];
Next if you are working to show a list of filtered product on a grid or something like this we need a way to know when the user changes the filter criteria. we could use event binding and watch for key presses or value changes, but an easier way is to change our _listFilter property into a getter and setter, like this
get listFilter: string {
return this._listFilter;
}
set listFilter(value:string) {
this._listFilter= value;
}
next we want to set our filteredProducts array to the filtered list of products like this
set listFilter(value:string) {
this._listFilter= value;
this.filteredProducts = this._listFilter? this.performFilter(this._listFilter) : this.products;
}
in preceding code we are using js conditional operator to handle the posibility that _listFilterstring is empty, null or undefined.
Next we use this.performFilter(this._listFilter) to filter our list.
performFilter(filterBy: string): any[] {
filterBy = filterBy.toLocaleLowerCase();
return this.products.filter((product: any) =>
product.productName.toLocaleLowerCase().indexOf(filterBy) !== -1);
}
Finally we should assign the main list of products to the filteredProducts and _listFilter to what we want.
constructor() {
this.filteredProducts = this.products;
this._listFilter= 'foo-bar';
}
last step is to change our template to bind to our filteredProducts property.

Resources