Add callback to function that is called from inside arr map method - reactjs

I need to map over an array in my state and assign the returned value to another property in my state.
I then need to call a function using the value of the updated property as a parameter, wait for this function to complete and then move on to the next item in my array map method before repeating the process.
The problem is that I think my function is being run before the state has been updated through each iteration of my arr.map method.
I think I need to utilise the componentDidUpdate() method before running my function, but I am not sure how to implement that in this scenario.
Simpler to explain through code example, see below (edited for simplicity):
state = {
a: [ {name: 'some string'}, {name: 'some string'}..... ],
b: '' // empty string
}
// when button is clicked, this function is run
myFunc() {
this.state.a.map( (item) => {
this.setState({
b: item.name
})
mySecondFunc()// perform next part of the loop
})
}
mySecondFunc() {
alert( this.state.b )
}
The alert in mySecondFunc() does not return anything, it is not being updated before the function is run.
What I need to happen is that the map will get the first item from my states 'a' array, assign it to state 'b' and run mySecondFunc().
I need to wait for state to be updated, before calling mySecondFunc, and then wait for mySecondFunc() to end its function before the map gets the next item from my state's 'a' array and calls mySecondFunc again.
This is the part that I cannot figure out.

try this
state = {
a: [ {name: 'some string'}, {name: 'some string'}..... ],
b: '' // empty string
}
// when button is clicked, this function is run
myFunc(){
this.state.a.map(async(item) => {
await this.setState({
b: item.name
},async () => {
await mySecondFunc()// perform next part of the loop
})
})
}
mySecondFunc() {
alert( this.state.b )
}
//OR
myFunc(){
this.state.a.map(async(item) => {
await mySecondFunc(item)
})
}
mySecondFunc(item) {
alert( item )
}

What I have understood from the problem description is that the goal here is to pass b's value sequentially to mySecondFunc . According to my understanding of the problem, I have modified your code :
myFunc() {
this.state.a.map( (item) => {
this.setState( (prevState) => {
const modifiedName = item.name;
this.mySecondFunc(modifiedName);
return {
b: modifiedName
}
});
});
}
mySecondFunc(name) {
alert( name );
}

Related

ANGULAR Components array key in result get value by id

this.crudService.get('user.php?mode=test')
.subscribe((data:any) => {
{ for (var key in data) { this[key] = data[key]; } };
}
);
This use to work on angular 7 now on angular 13 i get this error (look image)
In template i was using the values for example in json string was and array and i had users, in template was {{users}} , {{posts}} etc.. now the this[key] give error , please help me out its very important can't find solution
i'll show an example code, and then applied to your code:
Example
// creating global variables to receive the values
users: any = null;
posts: any = null;
// simulating the data you will receive
data: any[] = [
{users: ['user1', 'user2', 'user3']},
{posts: ['post1', 'post2', 'post3']}
];
getCrudService() {
// access each object of the array
this.data.forEach(obj => {
// getting keys name and doing something with it
Object.keys(obj).forEach(key => {
// accessing global variable and setting array value by key name
this[String(key)] = obj[String(key)]
})
})
}
Apllied to your code
this.crudService.get('user.php?mode=test').subscribe((data:any) => {
data.forEach(obj => {
Object.keys(obj).forEach(key => {
this[String(key)] = obj[String(key)]
});
});
});
I hope it helped you, if you need help, just reply me.

React : Pushing result of map() to an array

Hello I am trying to map through an array of objects and push them to a new array.
My ISSUE : only the last item of the object is being pushed to the new array
I believe this has to do with React life cycle methods but I don't know where I should I loop and push the values to the array to get the full list
//My object in an array named states
var states = [{"_id":"Virginia","name":"Virginia","abbreviation":"VN","__v":0},{"_id":"North Carolina","name":"North Carolina","abbreviation":"NC","__v":0},{"_id":"California","name":"California","abbreviation":"CA","__v":0}];
export function StateSelect()
{
**EDIT 1**
const options = [];
function getStates()
{
//This is how I am looping through it and adding to an array
{ states.length > 0 &&
states.map(item =>
(
console.log(`ITEM: ${JSON.stringify(item)}`),
options.push([{ value: `${item.name}`, label: `${item.name}`}])
))
}
}
return( {getStates()}: );
}
Thank you
It looks like your getStates() might not even be returning anything... but assuming it is, I believe you should be able to accomplish this using a forEach() fn in order to push values into your options array... Try adding the following into your map:
states.map((item) => {
console.log(`ITEM: ${JSON.stringify(item)}`);
let processed = 0;
item.forEach((i) => {
options.push([{ value: `${i.name}`, label: `${i.name}`}]);
processed++;
if(processed === item.length) {
// callback fn, or return
}
}
.map usually used to return another result, you could just use .forEach
In fact, you don't really need to declare options at all, just use .map on state to return the result would be fine.
return states.length > 0 && states.map(({ name }) => {
return { value: name, label: name };
});

store array into global variable angular

I am trying to save the value of parse array into global array.
but global array showing me undefined
dataUrl: string = "assets/data.csv";
private data:[];
dataInit(){
this.papa.parse(this.dataUrl, {
download: true,
complete: (result) => {
// result.data.push(this.data);
this.data = result.data
// console.log(result.data, "inside parser");
// console.log(this.data, "global array");
}
});
}
ngOnInit() {
this.dataInit();
console.log(this.data, "inside onInit");
}
Console
undefined "inside onInit"
There are two reasons for that -
You need to initilize the variable like this private data: Array<any>= [];
You are binding the value into asyn method and consoling the value in synchronous way.
The data will be available inside complete callback. So console.log(this.data) over there.
Reason: complete is a callback method which works asynchronously.
dataUrl: string = "assets/data.csv";
data = [];
dataInit(){
this.papa.parse(this.dataUrl, {
download: true,
complete: (result) => {
// result.data.push(this.data);
this.data = result.data
console.log(this.data);
}
});
}
ngOnInit() {
this.dataInit();
}
Change the initialization of the data property to something like
private data = [];
Or
private data: Array<T> = []
Instead of T type your array accordingly
Put the console log inside the complete function of the async code.
Because the papa.parse download code is asynchronous, the console log will show the initial value of data because the results are not ready yet.
Because this.papa.parse function is asynchronous, you can't get value of data variable right after calling dataInit... better to do inside complete callback
dataUrl: string = "assets/data.csv";
private data:[];
dataInit() {
this.papa.parse(this.dataUrl, {
download: true,
complete: (result) => {
this.data = result.data
this.toDo();
}
});
}
ngOnInit() {
this.dataInit();
}
toDo(){
console.log(this.data, "global array");
}

Best way to remove a specific item in AsyncStorage

I'm storing an array of objects in AsyncStorage and would like to know the best way to remove a specific object. Right now I´m passing an id to my function and then I loop through the array to match the id and remove the object and then the array in AsyncStorage is updated. This seems to work ok, but I wonder if this is optimal or if there is a better way to do this?
My function right now:
export function removeData(id) {
AsyncStorage.getItem('#books')
.then((books) => {
const updatedBooks = (JSON.parse(books))
for (let i = 0; i < updatedBooks.length; i++) {
if(updatedBooks[i].id == id) {
updatedBooks.splice(i, 1);
}
}
AsyncStorage.setItem('#books', JSON.stringify(updatedBooks));
})
}
My function for adding data to AsyncStorage:
export function addData(book) {
AsyncStorage.getItem('#books')
.then((books) => {
const b = books ? JSON.parse(books) : [];
b.push(book);
AsyncStorage.setItem('#books', JSON.stringify(b));
});
}
Button to add data with sample data to show structure:
<Button
title = "Add book"
onPress={() => addData({
id: 1,
title: 'Harry Potter',
author:'J.K. Rowling',
thumbnail:'https://covers.openlibrary.org/w/id/7984916-M.jpg',
})
To remove single item
AsyncStorage.removeItem('key', (err) => {
// key 'key' will be removed, if they existed
// callback to do some action after removal of item
});
To remove multiple items
let keys = ['k1', 'k2'];
AsyncStorage.multiRemove(keys, (err) => {
// keys k1 & k2 removed, if they existed
// callback to do some action after removal of item
});
Reference:
RemoveItem method
MultiRemove method

Can I update various items in an Immutable List in a React/Redux App

On submitting a form with some updated values, I need to update the state to reflect these changes, but I am new to Immutable.js and am unsure how to do so.
Is it possible to pass a function as a 2nd argument to set or update to update values based on certain criteria.
I have a function which receives state and an array of objects called values. The data in values looks like this:
[
{
key: 'name',
value: 'fred'
},
{
key: 'height',
value: '201'
},
{
key: 'weight',
value: '78'
}
]
I need to map over this data, and the state list, and update the corresponding values in the state list with the values array.
How can I do this. I have put together a function which the Reducer calls to update the state with the new data, but unsure exactly how to get the end result
function updateValue(state, values = []) {
const items = state.get('items').map((i) => {
const key = i.get('key');
values.map(v => {
if (v.key === key) {
return state.update('value', v.value);
}
})
});
return state.update('items', /* Can I use a function here to replace the code above.. to update all of the items in the state List that correspond to the items in the measurements array (which have new values) */);
}
Thank you very much.
Update
Tried the following, but getting the error: Expected [K, V] tuple: i
function updateValue(state, values = []) {
const items = state.get('items').map((i) => {
const key = i.get('key');
values.map(v => {
if (v.key === key) {
return state.update('value', v.value);
}
})
});
return state.update('items', items);
}
More details on the error from Immutable:
function validateEntry(entry) {
if (entry !== Object(entry)) {
throw new TypeError('Expected [K, V] tuple: ' + entry);
}
}
You can use 'merge' to return new object:
return state.merge({
items: values,
});

Resources