After subscribe save value into array or variable - javascript

I want to save the data after http request and subscribing like below but I cant see the data at the first index. It looks like this within the browser. With this.mySet[0] I have not access to this. What it wrong?
[]0: "test"length: 1__proto__: Array(0)
api.service.ts:409
myComponent.ts
mySet = [];
getLageSub() {
this.apiService.getLage().subscribe(data => {this.mySet.push(data)});
console.log(this.mySet)<------here is my output but I will need it elsewhere
}
myService.ts
getLage() {
let url = 'rest/getData-pool';
try {
return this.http.post(url, {}, this.getPutHeaders()).map((res) =>res.json())
} catch (error) {
console.log(error);
}
}

I hope it will help:
mySet : any;Constructor(){this.mySet = [];}
getLageSub() { this.apiService.getLage().subscribe(data => {this.mySet.push(JSON.parse(JSON.stringify(data)))}); console.log(this.mySet)<------here is my output but I will need it elsewhere }

Try this case :
mySet : any;Constructor(){this.mySet = [];}
getLageSub() { this.apiService.getLage().subscribe(data => {this.mySet.push(data)}); console.log(this.mySet)<------here is my output but I will need it elsewhere }

Related

How can I get the value stored in that array 'my_array' Cypress?

cy.get(tableBody)
.each(($el, $index) => {
let myArray = []
let mydata = $el.text()
if($index!==1) {
myArray.push(mydata.trim())
}
}).then((my_list) => {
cy.log(my_list)
Here, my_list print the value same as what cy.get(tableBody) return. It's like cy.get(tableBody).then((my_list) => { cy.log(my_list) }. I want that array and use that later. I know I can get return like this
TableDataBeforeSorting() {
let myArray = []
cy.get(tableBody).each(($el, $index) => {
let mydata = $el.text()
if($index!==1) {
myArray.push(mydata.trim())
}
})
return myArray
But I want it using then so that I can use it later. Any suggestion or feedback will be highly appreciated.
I've found that when Cypress doesn't do what I want in terms of saving data to variables to use later, I can save data to disk:
// save it
cy.XYZcommand().then((results) => {
cy.writeFile('temp.txt', results)
})
...
cy.readFile('temp.txt')
.then((results) => {
// do something with it
})
...
// clean it up
cy.exec('rm temp.txt')

React JS state array empty inside function but items appear in render

I'm writing this react component to render all chats of an user in a chat app.
The conversation list is acquired from a REST end point and set as a state variable.
When a new message arrives through socket, I'm trying to bring the conversation in the list to the top and mark it in a different color.
The code for that looks like the following:
const [conversationsList, setConversationsList] = useState([]);
//When a new message arrives,
const markNewConversation = (message) => {
console.log(conversationsList); //Empty array
let newConversationList = conversationsList.map((conversationElement) => {
if (conversationElement.thread_id === message.thread_id) {
conversationElement.date_created = message.date_created;
conversationElement.new_for.push(user._id);
}
return conversationElement;
});
console.log(newConversationList);
newConversationList = newConversationList.sortBy(function (o) {
return o.date_created;
});
console.log(newConversationList); //Empty as well.
setConversationsList(newConversationList); //Whole screen goes black on this.
};
useEffect(() => {
if (user._id === null) history.push("/");
connectSocket();
socket.on("_messageIn", markNewConversation);
getThreads().then((threads) => {
threads.forEach((thread, index) => {
let allParticipants = thread.thread_participants;
threads[index].other_user = allParticipants.find((participant) => {
return participant._id != user._id;
});
});
setConversationsList(threads);
setIsLoading(false);
});
// returned function will be called on component unmount
return () => {
socket.off("_messageIn", markNewConversation);
};
}, []);
return conversationsList.map((conversation) => {
return(//magically appears inside this div.)
})
The problem is when a new message arrives, the function receives an empty array and the entire screen becomes empty. I'm not even setting the array to empty anywhere. Where am I going wrong?
In this function you're mutating objects, this can cause weird errors.
let newConversationList = conversationsList.map((conversationElement) => {
if (conversationElement.thread_id === message.thread_id) {
conversationElement.date_created = message.date_created;
conversationElement.new_for.push(user._id);
}
return conversationElement;
});
it should look like this:
let newConversationList = conversationsList.map((conversationElement) =>
(conversationElement.thread_id === message.thread_id) ? {
...conversationElement,
date_created: message.date_created,
new_for: [...conversationElement.new_for, user.id]
} : {
...conversationElement,
new_for: [...conversationElement.new_for]
}
There is a concept in javascript of State Mutating and we should never mutate the objects directly. Here you are making the mistake is that when new message comes it replaces whole object with new one and kind of re-initialize it. So spread the state using spread operator before adding new message.
Do like this:
let newConversationList = conversationsList.map((conversationElement) =>
(conversationElement.thread_id === message.thread_id) ? {
...conversationElement, //spread/copy like this before mutating
date_created: message.date_created,
new_for: [...conversationElement.new_for, user.id]
} : {
...conversationElement, //spread/copy like this before mutating
new_for: [...conversationElement.new_for]
}

Filter API response directly in URL

I would like to know if it is possible to filter the response of an API directly via the URL.
URL API : https://coronavirus-19-api.herokuapp.com/countries
I only put 2 countries for the example but the structure of the answer is like this:
[
{
"country":"USA",
"cases":176518,
"todayCases":12730,
"deaths":3431,
"todayDeaths":290,
"recovered":6241,
"active":166846,
"critical":3893,
"casesPerOneMillion":533,
"deathsPerOneMillion":10,
"firstCase":"\nJan 20 "
},
{
"country":"Italy",
"cases":105792,
"todayCases":4053,
"deaths":12428,
"todayDeaths":837,
"recovered":15729,
"active":77635,
"critical":4023,
"casesPerOneMillion":1750,
"deathsPerOneMillion":206,
"firstCase":"\nJan 29 "
}
]
For the moment in my project I collect all the responses and I filter afterwards to have only the data for a country but to optimize performance I would like to filter the responses directly by URL.
async getCountryStats() {
try {
let response = await fetch("https://coronavirus-19-api.herokuapp.com/countries")
if (response.status === 200) {
let data = await response.json()
// Data object with ID
data = Object.assign({}, data)
// Data object with name of property
let obj = {}
for (let i in data) {
obj = { ...obj, [data[i].country]: data[i] }
}
this.setState({ focusStats: obj[this.state.focusCountry] })
} else {
this.setState({ errorStatus: true })
console.error('Error status')
}
} catch (err) {
console.error(err)
}
}
I use React, here is my repository: https://github.com/michaelbaud/covid19, here is the rendering: https://suspicious-kilby-d90f99.netlify.com
You can use the following link instead:
https://coronavirus-19-api.herokuapp.com/countries/{country-name}
For example in your case it would be:
USA : https://coronavirus-19-api.herokuapp.com/countries/USA
Italy : https://coronavirus-19-api.herokuapp.com/countries/italy
Good Luck

Promise.resolve() return only one element in nested array

Here is my code:
search(): Promise<MyModel[]> {
const query = {
'action': 'update',
};
return new Promise((resolve, reject) => {
this.api.apiGet(`${API.SEARCH_STUDENT}`, query).then((data) => {
const a = data.items.map(i => i);
const b = data.items.map(i => i);
console.log(a.array1[0].array2.length); // 1
console.log(b.array1[0].array2.length); // 5
resolve(a);
}, (error) => {
reject(error);
});
});
}
MyModel class:
class MyModel {
...
array1: [{
array2: []
}]
}
data.items[0].array1[0].array2 returned by function apiGet contains 5 elements. But if I put a or b into resolve function, it now just keep first element only like the comments in the snippet.
Could anyone show what I miss here?
Firstly I am not sure why you wrap a promise in a promise.. why do you need to do that when
this.api.apiGet returns a promise.
Also, why are you trying to map? I bet if you console.log(data.items) the same data would come back. I think you have just got a little confused with your code. A tidy up of the code should resolve all of this for you.
I would do something like the below, now every time you call search you get all the data back which you can use when you want it.
search(): Promise<MyModel[]> {
const query = {
'action': 'update',
};
return this.api.apiGet(API.SEARCH_STUDENT, query)
.then((data) => data as MyModel[]));
}

Reducer cannot read property 'photos' of undefined? What am I doing wrong?

Here is the initial state of my reducer, and I need to set it up in this way due to some post processing I need to do:
const initialState = {
showAll: {
photos: null
}
}
Basically, I have a page where you see all your photos, and you can tag certain ones as your pinned photos.
Here's part of my reducer logic:
if (state.showAll.photos) {
const showAllState = state.showAll.photos;
showAllState.map(m => {
if (action.payload.id === m.id) {
m.pinned = true;
}
});
showAllAfterPin = showAllState;
} else {
showAllAfterPin = state.showAll.photos;
}
However, I get an error saying cannot read property 'photos' of undefined and I'm not sure what I am doing wrong.
Might be easier to just set your photos in initialState to empty array [] instead of null.
Another thing, your reducer should not mutate your state object.
Doing const showAllState = state.showAll.photos doesn't make it a new object.
Last thing, showAllState.map(...) needs to return an item inside the function body. It will create a new array.
Here's something you can do...
const { photos = [] } = state.showAll;
const updatedPhotos = photos.map(photo => {
if (action.payload.id === photo.id) {
return Object.assign({}, photo, { pinned: true })
}
return photo;
});
// return entire state if this is inside your root reducer
return {
...state,
showAll {
...state.showAll,
photos: updatedPhotos
}
}

Categories

Resources