Alternative for ForEach loop in Javascript? - javascript

I'm working with array where it contains array of array object and I tried with ForEach loop now its working fine but I want to know any way to improvise the performance of my array and combined into key value pair as my final result.
0:
Project: {Division__c: "Mechanical", Owner: {…}, Id: "009921",OwnerId: "005C00000049TRKIA2", …}
TaskList: Array(1)
0:
Case: {Owner: {…},Priority: "Normal", Id: "00118627"}
and my code is
Project.forEach(wrappedProject => {
result.push({'label':Project.TaskList.Owner.Name,'value':wrappedProject.TaskList.Owner.Name})
Project.TaskList.forEach(Task =>{
Task.Case.forEach(task => {
console.log('task',task)
ownerResult.push({'label':task.Owner.Name,'value':task.Owner.Name})
});
})
});

Related

Array Spread Syntax not working as expected on React State Variable

Hi I'm trying to take some data from my Firebase Firestore and save it to state in my React app. My code is this:
const [firebaseOrders, setFirebaseOrders] = useState([])
useEffect(() => {
const getOrders = async () => {
const querySnapshot = await getDocs(collection(db, `users/carlos#example.com/orders`));
querySnapshot.forEach((doc) => {
const newOrder = doc.data()
setFirebaseOrders([...firebaseOrders, newOrder])
})
}
getOrders();
}, [])
console.log(firebaseOrders)
I am expecting to get an array of objects with my orders. Instead my array is not saving when I use the spread operator so I end up with just the last item in my array:
Here's a pic of what I get in the console
[{…}]
->0 : {titles: Array(2), timestamp: nt, prices: Array(2), amount: 869.99, amount_shipping: 6.99, …}
length : 1
->[[Prototype]] : Array(0)
[{…}]
->0 : {amount: 78.29, timestamp: nt, titles: Array(2), amount_shipping: 0, prices: Array(2), …}
length : 1
->[[Prototype]] : Array(0)
I feel like I am missing something basic, can anyone help me out?
Modifying state is an asynchronous operation, so doing this in a tight loop (as you do) means that you're overwriting the previous value each time.
Instead, call setFirebaseOrders just once with all results:
setFirebaseOrders(
querySnapshot.docs.map((doc) => doc.data());
})
Also note that the console.log(firebaseOrders) may not show the correct value, as it likely runs before setFirebaseOrders(...) has run/completed.
If you want to see the orders from the state, show them in components in your UI. If you want to console.log what you get from the database, do so in the callback:
const orders = querySnapshot.docs.map((doc) => doc.data());
console.log(orders);
setFirebaseOrders(orders);

Error getting specific API response location which is pushed in an array

I'm storing the API in the global array (tempdata) and when I print tempdata I'll get the response stores in the array but the problem here is when I try to get the specific array location like tempdata[0] or tempdata[1] it gives me undefined.
error if I use console.log(tempdata[0]);
printed array on console:
tempdataaa
[]
0: {values: {…}, series: Array(1), truncated: false}
1: {values: {…}, series: Array(1), truncated: false}
length: 2
__proto__: Array(0)
component code:
let tempdata: any =[];
for (let a = 0; a < this.checkDevice.length; a++) {
this.httpRequestService.ChartData(this.dateTo, this.checkDevice[a], this.mergeactive[0][a],
this.dateFrom).then(mresp => {
tempdata.push(mresp) ;
});
}
That's because you're trying to access object like an array. To do that you should map every object and push it into the array like this:
.then(mresp => {
const mapped = Object.keys(mresp).map(key => mresp[key]);
//now you can log map element and access it with indexes
});

React Rest API issue

I´m new to REST API and on the current project where I can create gallery categories and images inside the gallery I bumped into a problem.
I have multiple objects within the parent array as seen below. Some of them containing image.
[]
0:
0: {path: "test", name: "test"}
1: {path: "puli", image: {…}, name: "puli"}
2: {path: "animalsg", name: "animalsg"}
3: {path: "animals", image: {…}, name: "animals"}
4: {path: "Animals", image: {…}, name: "Animals"}
5: {path: "sdfsf", name: "sdfsf"}
6: {path: "viki", name: "viki"}
7: {path: "pul", image: {…}, name: "pul"}
8: {path: "testik", name: "testik"}
__proto__: Object
length: 1
__proto__: Array(0)
Is there a way to fetch all the name values from each object and also assign it an id?
Can you please help me modify this useEffect for this purpose?
useEffect(() => {
const tempAlbum = [];
fetch('http://someapi.xy/gallery')
.then(response => response.json())
.then(data => tempAlbum.push('???'));
}, [])
If I understood right, you would want to do something like this
useEffect(() => {
const tempAlbum = [];
fetch('http://someapi.xy/gallery')
.then(response => response.json())
.then(data => { data[0].forEach(
(item,i) => {
tempAlbum.push({name: item.name, id: i})
})
});
}, [])
About the id, this approach is using the same array index as id, that could work for you unless you need this id to render this array on your React application, in which case using the index is not recommended, so you could use a library like uuid to generate an id on the fly, it's very simple to use and does not require configuration.
If what you are trying to do is simply get an tempAlbum to have an array of like [{ name: 'rockers', id: '1234'}, ...] then you can do:
data.flat().forEach((x, idx) => tempAlbum.push({ name: x.name, id: idx }));
That should work for you.

RXJS Observables - http call for each index value and merge result

I do a http call to get an Array with objs. And now I want to call for each objs that return me an ID another http call. After all I want to have one observable result.
So far I managed to get for each index a http call. The problem instead of one result I got multiple.
getStats(tag: string) {
return this.service.getClanByClanTag(tag)
.map(clan => {
return clan.memberList; //the arr that return the ID's
})
.switchMap((member: PlayerByMemberListType[]) => {
return member; // singleObj of the arr
})
.concatMap((singleMember) => {
return this.service.getPlayerData(singleMember.tag).map(player => {
//push data to the new arr which should return only one time
this.newArr.push({
tag: singleMember.tag,
name: singleMember.name,
warStars: player.warStars,
trophiesNightBase: singleMember.versusTrophies
});
return this.newArr;
});
});
}
This is what the console prints out after subscribing to it:
Array [ {…} ]
Array [ {…}, {…} ]
Array(3) [ {…}, {…}, {…} ]
Array(4) [ {…}, {…}, {…}, {…} ]
Array(5) [ {…}, {…}, {…}, {…}, {…} ]
...
I know I need some kind of Observable.forkJoin but I don't know how integrate it in the code.
Try something like this:
this.service.getClanByClanTag(tag)
.mergeMap(clan => clan.memberList)
.mergeMap(
member => this.service.getPlayerData(member.tag), // supposedly this returns an observable
(member, player) => ({
tag: member.tag,
name: member.name,
warStars: player.warStars,
trophiesNightBase: member.versusTrophies
})
)
.toArray()
So basically what you want to achieve is this.
Get the clan info
Using clan info from step 1, get the memberList in the clan
For each member inside the memberList, get the players
You will need to think of a way to preserve the info at step2 when before switchMap in step3. Usually we will use a Subject, but in the case if you do not want to, simply map the Observable to preserve the data:
getStats(tag: string) {
return this.service.getClanByClanTag(tag)
.map(clan => {
return clan.memberList; //the arr that return the ID's
})
.switchMap((memberList: PlayerByMemberListType[]) => {
//note that the following map is a function of javascript array, not Observable
//it returns an array
let arrayOfObservables = memberList.map(singleMember => {
this.service.getPlayerData(singleMember.tag)
//map the data so as to preserve the data of singleMember
//by creating a new object, using Object.assign
.map(playerData => {
return Object.assign({memberData: singleMember}, playerData,)
});
})
return Observable.forkJoin(arrayOfObservables);
})
.map(players => {
//players is an array of Object that is the format of {memberData:singleMember, playerData:player)
//perform Object destructuring method
return players.map(({memberData,playerData}) => {
return {
tag: memberData.tag,
name: memberData.name,
warStars: playerData.warStars,
trophiesNightBase: memberData.versusTrophies
}
})
})
}

spread operator (...) is creating extra fields in array in es6

I wanted to embed a new key/value pair in the respective indexed array of objects based on an onChange event.
However, it is done correctly but adding extra elements in the array.
Original array of objects:
0:{data: {…}}
1:{data: {…}}
2:{data: {…}}
3:{data: {…}}
4:{data: {…}}
Achieved result:
0:{data: {…}}
1:{data: {…}}
2:{data: {…}, origin: "UK"}
3:{data: {…}, origin: "UK"}
4:{data: {…}}
5:"UK"
6:"UK"
Intended result:
0:{data: {…}}
1:{data: {…}}
2:{data: {…}, origin: "UK"}
3:{data: {…}, origin: "UK"}
4:{data: {…}}
Below is my code doing it in a loop:
render: (rowData, indexes) => {
return (
<SelectField
id={`origin-${indexes.rowIndex}`}
defaultValue="US"
style={{ position: 'absolute' }}
onChange={text => {
this.setState(
{
generalPermitSelectedVehicles: [
...generalPermitSelectedVehicles,
(generalPermitSelectedVehicles[
indexes.rowIndex
].origin = text),
],
},
() => {
console.log({
generalPermitSelectedVehicles: this.state
.generalPermitSelectedVehicles,
});
},
);
}}
menuItems={[
{
label: 'America',
value: 'US',
},
{
label: 'United Kingdom',
value: 'UK',
},
{
label: 'Oman',
value: 'Oman',
},
]}
/>
);
},
Write it like this:
this.setState(prevState => {
let data = [...prevState.generalPermitSelectedVehicles];
data[indexes.rowIndex].origin = text;
return {generalPermitSelectedVehicles: data};
})
Why its failing in your case?
Because when you do:
[...arr, (arr[index].origin=10)]
It will do two things, first it will update the value of origin at that index, second it will add 10 (returned 10 from ()) at the end of array also.
Check this snippet:
let arr = [{a:1}, {a:2}, {a:3}];
arr = [...arr, (arr[1].a=500)]; //500 will get added in the last
console.log('new value', arr);
Suggestion: Use updater function (prevState) because next state (value) of generalPermitSelectedVehicles is dependent on previous value.
Check the DOC for more details about setState updater function.
You need to update the original state and not append it. You are not using spread operator correctly. Also make use of functional setState when you want to update state based on prevState. You would need to do
this.setState(
prevState => ({
generalPermitSelectedVehicles: [
...prevState.generalPermitSelectedVehicles.slice(0, index.rowIndex),
{...prevState.generalPermitSelectedVehicles[
indexes.rowIndex
], origin: text},
...prevState.generalPermitSelectedVehicles.slice(index.rowIndex + 1)
],
},
() => {
console.log({
generalPermitSelectedVehicles: this.state
.generalPermitSelectedVehicles,
});
},
);
The error in your approach is that you are appending the updated state after spreading the original state, you need to update the existing instead.
Also check this answer on how to update nested state

Categories