I have an existing array that as I scroll, I am trying to add more elements to.
I am using rss2json to convert an rss feed to json.
ngOnInit() {
this.getRssFeed(); // returns 4 items
}
Here is how I am adding more items:
this.count++;
this.podcastService.getRssFeed(this.rssUrl, this.count)
.then(data => {
if (data) {
for (const episodes of data.items) {
this.episodes.push(episodes); // returns 5 items
// const episode = this.episodes[episodes.length - 1]
}
event.target.complete();
console.log(data);
...
Count is correctly getting incremented. But each time getRssFeed is called the entire array is returned. Each time with the correct length.
I am not sure how to pop all of the array elements that come back except for the last one.
I've also tried something like this to try and push() only the last array element returned. Still no luck.
const episode = this.episodes[episodes.length - 1]
For example, if on initial load I get:
[foo, bar]
when I scroll, I am getting back:
[foo, bar, baz]
I only want to add baz to the already existing array.
Thank you for any suggestions!
One solution you can try is to change the next portion of code:
if (data)
{
for (const episodes of data.items)
{
this.episodes.push(episodes); // returns 5 items
// const episode = this.episodes[episodes.length - 1]
}
...
}
By this one:
if (data)
{
let lastEpisode = data.items.pop();
this.episodes.push(lastEpisode);
...
}
Here, pop() is used to remove the last element from data.items array and returns that element, we save it on the variable lastEpisode and finally we push it on your episodes array. Another solution, that won't change data.items array could be:
if (data)
{
let lastEpisode = data.items[data.items.length - 1];
this.episodes.push(lastEpisode);
...
}
From what I understand, you want to add just the latest items returned from the getRssFeed service to the episodes list. You can make use of the Array spread syntax to update the episodes list on every call of the getRssFeed service.
You can update the function to make it look like this:
this.count++;
this.podcastService.getRssFeed(this.rssUrl, this.count)
.then(data => {
if (data) {
this.episodes = [
// This keeps the previous episodes
...this.episodes,
// This adds the last item returned to the array
data.items[data.items.length -1],
]
}
event.target.complete();
console.log(data);
...
Related
I have an array of objects. The object contains two enteries I want to delete one entry and refresh the page with only one entry loading on the page.
array
the form looks like this
The array looks like this and the data on my page looks like
this.
The functionality I want is if I click on any entry it deletes one entry only and refreshes with the remaining three entries. If I click one the other entries two three and four should be visible and one deleted
Currently, if I click on one entry to delete it deletes both entries from the current searched index if the id matches.
const [standup, setStandup] = useState({
yesterday: {
entry:"",
id:""
},
today: {
entry:"",
id:""
}
});
const [allStandups, setAllStandups] = useState([]);
checked here to delete only entries from yesterday but it is deleting the whole index both entries inside the id.
function deleteItem(id) {
setAllStandups((prevStandup)=>{
return prevStandup.filter((standup) => {
return (standup.yesterday.id !== id;
});
})
}
`function deleteItem(id) {
setAllStandups((prevStandup)=>{
return prevStandup.map((standup) => {
if(standup.yesterday.id === id){
return {...standup.today}
}
else{
return {...standup.yesterday};
}
});
})
}`
this will delete only clicked value.
It is not array, It should be deleting the node from JSON Object.
function deleteItem(NodeName,precStandup) {
delete precStandup[NodeName];
return precStandup;
}
let result=deleteItem("yesterday",standup);
I'm attempting to add an object at a specific point in my 'data' array which is this components state. The following isn't working, the array simply gets emptied.
addNewBulletAfterActive = () => {
const array = this.state.data;
const newBulletPoint = {
id: this.state.data.length += 1,
title: 'Click to add'
};
const newData = array.splice(this.state.activeBulletPointId, 0, newBulletPoint);
this.setState({
data: newData
});
}
The idea is that if I have a list of 10 bullet points, the user can click on the 4th bullet point and press enter to add a new bullet point directly after. I've not had any issues adding items to the end of the array but it looks like .splice is causing issues.
I believe this should do what you're after.
function addAfter(array, index, newItem) {
return [
...array.slice(0, index),
newItem,
...array.slice(index)
];
}
This function returns a new array with a new item inserted in the middle. It doesn't mutate your original array and so will play nicely with component's state and Redux.
You can then assign the output from this function to your state.
splice returns spliced items (which is empty since you splice 0 items) and mutates original array.
const newData = array.slice(0); // copy
newData.splice(this.state.activeBulletPointId, 0, newBulletPoint);
this.setState({
data: newData
});
I think this could be an easier and faster method to do this
/*Just plain JS*/
function AddAfter(array, newObject){
array.unshift(newObject);
}
/*In react If updating state*/
var _prev = this.state.your_array; //getting the current value for the state object
var newInfo = {id: 1, more: 'This is a new object'};
_prev.unshift(newInfo);
I am trying to create a loop that will select the 'Photos' from each element in the array. However, they have no index numbers so I can't use a traditional for loop, using the loop iteration to select the next object each time. I can't seem to find a method that allows the selector to change each time the loop occurs.
This is what I have:
function fetchHalls() {
halls = [];
fetch(`https://www.data.brisbane.qld.gov.au/data/dataset/d14761ac-9bd9-4712-aefd-4bace8ca7148/resource/d7a4821d-eb68-454a-9615-356e17fd805b/download/bcccommunityhalls.json`)
.then(resp => resp.json())
.then(data => {
halls = halls.concat(data);
console.log(halls[0].Halls[ 'Acacia Ridge Hall' ].Description[4].Photos);
});
}
I basically want to change 'Acacia Ridge Hall', to the next hall name in the array and do that for as many halls are in the array. Which I also tried but '.length' returned nothing.
Here is a snippet of what the structure looks like:
Here's my solution:
for(let hall of Object.keys(data.Halls)) {
// Here hall is the hallname, e.g, "Acacia Ridge Hall"
// and data.Halls[hall] // is the value
const urls = data.Halls[hall]?.Description[4]?.Photos;
if(urls) {
// whatever you want to do with the urls
}
}
Firstly, you can get rid of concat if you are sure that the data returned from the server is always in Pascal Case.
I have assumed in the below code that it always returns the data in Pascal Case. You could use either one of two methods to loop through the objects returned from the server:
Object.values(halls)
Object.keys(halls)
Sample Code:
var halls = [];
fetch(`https://www.data.brisbane.qld.gov.au/data/dataset/d14761ac-9bd9-4712-aefd-4bace8ca7148/resource/d7a4821d-eb68-454a-9615-356e17fd805b/download/bcccommunityhalls.json`)
.then(resp => resp.json())
.then(data => {
halls = data.Halls;
//1st method
for (let value of Object.values(halls)) {
// Here loop through the description to access photo elements
console.log('value', value.Description)
}
//2nd method
Object.keys(halls).map(function (element, index, array) {
console.log("element", element);
console.log("index", index);
console.log("array", array);
});
});
I want to retrieve a list of products in relation to the user's position, for this I use Geofirestore and update my Flatlist
When I have my first 10 closest collections, I loop to have each of the sub-collections.
I manage to update my state well, but every time my collection is modified somewhere else, instead of updating my list, it duplicates me the object that has been modified and adds it (updated) at the end of my list and keep the old object in that list too.
For example:
const listListeningEvents = {
A: {Albert, Ducon}
B: {Mickael}
}
Another user modified 'A' and delete 'Ducon', I will get:
const listListeningEvents = {
A: {Albert, Ducon},
B: {Mickael},
A: {Albert}
}
And not:
const listListeningEvents = {
A: {Albert},
B: {Mickael},
}
That's my useEffect:
useEffect(() => {
let geoSubscriber;
let productsSubscriber;
// 1. getting user's location
getUserLocation()
// 2. then calling geoSubscriber to get the 10 nearest collections
.then((location) => geoSubscriber(location.coords))
.catch((e) => {
throw new Error(e.message);
});
//Here
geoSubscriber = async (coords) => {
let nearbyGeocollections = await geocollection
.limit(10)
.near({
center: new firestore.GeoPoint(coords.latitude, coords.longitude),
radius: 50,
})
.get();
// Empty array for loop
let nearbyUsers = [];
// 3. Getting Subcollections by looping onto the 10 collections queried by Geofirestore
productsSubscriber = await nearbyGeocollections.forEach((geo) => {
if (geo.id !== user.uid) {
firestore()
.collection("PRODUCTS")
.doc(geo.id)
.collection("USER_PRODUCTS")
.orderBy("createdDate", "desc")
.onSnapshot((product) => {
// 4. Pushing each result (and I guess the issue is here!)
nearbyUsers.push({
id: product.docs[0].id.toString(),
products: product.docs,
});
});
}
});
setLoading(false);
// 4. Setting my state which will be used within my Flatlist
setListOfProducts(nearbyUsers);
};
return () => {
if (geoSubscriber && productsSubscriber) {
geoSubscriber.remove();
productsSubscriber.remove();
}
};
}, []);
I've been struggling since ages to make this works properly and I'm going crazy.
So I'm dreaming about 2 things :
Be able to update my state without duplicating modified objects.
(Bonus) Find a way to get the 10 next nearest points when I scroll down onto my Flatlist.
In my opinion the problem is with type of nearbyUsers. It is initialized as Array =[] and when you push other object to it just add new item to at the end (array reference).
In this situation Array is not very convenient as to achieve the goal there is a need to check every existing item in the Array and find if you find one with proper id update it.
I think in this situation most convenient will be Map (Map reference). The Map indexes by the key so it is possible to just get particular value without searching it.
I will try to adjust it to presented code (not all lines, just changes):
Change type of object used to map where key is id and value is products:
let nearbyUsersMap = new Map();
Use set method instead of push to update products with particular key:
nearbyUsersMap.set(product.docs[0].id.toString(), product.docs);
Finally covert Map to Array to achieve the same object to use in further code (taken from here):
let nearbyUsers = Array.from(nearbyUsersMap, ([id, products]) => ({ id, products }));
setListOfProducts(nearbyUsers);
This should work, but I do not have any playground to test it. If you get any errors just try to resolve them. I am not very familiar with the geofirestore so I cannot help you more. For sure there are tones of other ways to achieve the goal, however this should work in the presented code and there are just few changes.
This sounds like a silly question but the docs say:
orderByKey
orderByKey() returns firebase.database.Query
Generates a new Query object ordered by key.
The query object is ordered by key which means i can do:
ref.orderByKey().limitToLast(1)
To get the last in order.
But if I do:
ref.limitToLast(1).on('child_added', function(s)
{
ref.orderByKey().limitToLast(2).once('value').then(function(snapshot)
{
var val = snapshot[Object.keys(snapshot)[0]];
});
});
Will val always be the second last? The docs don't specifically say the snapshot is ordered. Should I just continue to sort it myself to be sure?
Is there a better way to get the second last in order or the last if there is only one every time a child is added? Basically i want the one before the one that was just added.
Thanks!
You have this query:
ref.orderByKey().limitToLast(2)
This query orders the child nodes by key and then returns the last two items.
To access the results in order, use Snapshot.forEach():
ref.orderByKey().limitToLast(2).once('value').then(function(snapshot)
{
snapshot.forEach(function(child) {
console.log(child.val());
});
});
The first time through the loop will give you the second-to-last item, so if you want to capture that:
ref.orderByKey().limitToLast(2).once('value').then(function(snapshot)
{
var isFirst = true;
snapshot.forEach(function(child) {
if (isFirst) {
console.log(child.val());
isFirst = false;
}
});
});