I am using Firestore database to store my crypto trades. Since there are a lot of them, I have to load them using the .limit(numberOfTrades) query.
My query: const tradesRef = firebase.firestore().collection("trades").limit(15);
Inside my useEffect:
useEffect(() => {
tradesRef
.where("type", "==", "fiveMinutes")
.get()
.then((collections) => {
const tradesData = collections.docs.map((trade) => trade.data());
const lastDoc = collections.docs[collections.docs.length - 1];
setTrades(tradesData);
setLastTrades(lastDoc);
});
setDataLoading(false);
}, [filter]);
However, I do need pagination in order to load the next set of trades. The pagination of next is already implemented and fairly simple. This is the function I am using for next page:
const fetchMore = () => {
tradesRef
.startAfter(lastTrades)
.get()
.then((collections) => {
const tradesData = collections.docs.map((trade) => trade.data());
const lastDoc = collections.docs[collections.docs.length - 1];
setTrades(tradesData);
setLastTrades(lastDoc);
});
}
Now I am trying to figure out how to implement a previous page query that gets the previous 12 trades. I have researched and implemented a few queries but I am not even close to solving the issue. Any help would be appreciated.
If you want to paginate backwards, you need to use a combination of:
.endBefore(firstItemOnNextPage)
.limitToLast(12)
So firstItemOnNextPage is the first item on page N+1, where you're paginating backwards from. And you're then asking for the last 12 items before that anchor item.
Related
I'm trying to retrieve data from Firestore with the code below, but I only get one result. When I eliminate that document, I get the other document with the same query. I don't know what else to do.
const retrieveNetwork2 = async () => {
const query = geocollection.near({
center: new firebase.firestore.GeoPoint(15.5, -90.25),
radius: 1000,
});
await query.get().then((querySnapshot) => {
querySnapshot.docs.map((doc) => {
let workingX = doc.data().name;
setReada(workingX);
});
});
};
The problem is that for each document that you get back, you call setReada. So at the end of processing all documents, setReada will only know about the last document in the results.
It's hard to say what exactly you need to change without seeing your setReada, but it'll typically be something like:
query.get().then((querySnapshot) => {
let results = querySnapshot.docs.map((doc) => doc.data().name);
setReada(results);
});
So with this your setReada is now an array with the name value of each document.
I'm new to Next js and im trying to implement a live search input field, I'm not sure if I have done things right if im violating some principles of next by not using getServerProps for this matter, what I have currently done is simply call an API and save the result in a simple state
const handleInputChange = (event) => {
const query = event.target.value;
setQuery(query);
if (event.target.value.length < 3) {
setResults([]);
return;
}
setLoading(true);
fetchSearchResults(query);
};
const fetchSearchResults = async (paginate = "", query) => {
if (query === "") {
setResults([]);
}
const searchUrl = [uri];
await axios
.get(searchUrl)
.then((res) => setResults(res.data.results))
.catch((error) => setMessage("No data found"));
};
Is there a better way to do such thing in next js(production ready)? Thanks
edit:
I found a way that could probably solve this by using getStaticProps with revalidate, however this is a component in the header that's on all pages and not a page, getStaticProps won't work here, is there a way around this?
To be clear I have a list of products, and the header contains a search bar that would function as an input for live search of these products
I am trying to build a webpage with AngularFireStore as my data store. In order to enable infinite scrolling, I am trying to query the store with limit and startAfter functionality of AngularFireStore.
For some reason, I am not able to get it working. The limit functionality is not working as expected as it returns values greater / lesser than the actual limit, and there are duplicate values as well
I have searched and tried few approaches (this, this, this). But nothing works.
Here is what I have tried:
crudService.ts :
readNextPost(cursor){
return this.firestore.collection('MyCollection',
ref => ref.orderBy('date', 'desc')
.startAfter(cursor)
.limit(10)
).snapshotChanges();
}
component.ts
mapResponseToObject(data) {
return {
id: data.payload.doc.id,
doc: data.payload.doc
}
}
setLastPost(data) {
this.lastFetchedPost = data[data.length - 1].doc;
}
fetchNextPosts() {
this.crudService.readNextPost(this.lastFetchedPost).subscribe(data =>{
let nextPost = data.map(this.mapResponseToObject)
this.allPosts = [...this.allPosts, ...nextPost];
this.setLastPost(nextPost);
})
}
readNextPost returns values less than 10 although there are more than that in the store, and some times returns more than 10, which has values that were fetched earlier.
This causes duplicate data visible in the webpage.
As a newbie to both AngularFireStore and Angular 10, I am stuck at this issue for several hours. Any help would be much appreciated. Many thanks.
Try the subscribe:
this.firestore.collection('MyCollection',
ref => ref.orderBy('date', 'desc')
.startAfter(cursor)
.limit(10)
).get()
.subscribe(response => {
for (const item of response.docs) {
console.log(item.data());
}
});;
I think snapshotChanges is a stream of "Changes", not the full result of the query.I'm assuming that means changes to the result of the query but the docs aren't too clear:
https://github.com/angular/angularfire/blob/master/docs/firestore/collections.md#snapshotchanges
I am stuck in what I thought was a very simple use case: I have a list of client ids in an array. All I want to do is fetch all those clients and "watch" them (using the .onSnapshot).
To fetch the client objects, it is nice and simple, I simply go through the array and get each client by their id. The code looks something like this:
const accessibleClients = ['client1', 'client2', 'client3']
const clients = await Promise.all(
accessibleClients.map(async clientId => {
return db
.collection('clients')
.doc(clientId)
.get()
})
)
If I just needed the list of clients, it would be fine, but I need to perform the .onSnapshot on it to see changes of the clients I am displaying. Is this possible to do? How can I get around this issue?
I am working with AngularFire so it is a bit different. But i also had the problem that i need to listen to unrelated documents which can not be queried.
I solved this with an object which contains all the snapshot listeners. This allows you to unsubscribe from individual client snapshots or from all snapshot if you do not need it anymore.
const accessibleClients = ['client1', 'client2', 'client3'];
const clientSnapshotObject = {};
const clientDataArray = [];
accessibleClients.forEach(clientId => {
clientSnapshotArray[clientId] = {
db.collection('clients').doc(clientId).onSnapshot(doc => {
const client = clientDataArray.find(client => doc.id === client.clientId);
if (client) {
const index = clientDataArray.findIndex(client => doc.id === client.clientId);
clientDataArray.splice(index, 1 , doc.data())
} else {
clientDataArray.push(doc.data());
}
})
};
})
With the clientIds of the accessibleClients array, i create an object of DocumentSnapshots with the clientId as property key.
The snapshot callback function pushes the specific client data into the clientDataArray. If a snapshot changes the callback function replaces the old data with the new data.
I do not know your exact data model but i hope this code helps with your problem.
I have been doing this for an hour. I simply want to get the number of children in the child "Success" in the database below. The answers in similar stackoverflow questions are not working. I am new in Javascript Programming.
So far I have tried this
var children = firebase.database().ref('Success/').onWrite(event => {
return event.data.ref.parent.once("value", (snapshot) => {
const count = snapshot.numChildren();
console.log(count);
})
})
and also this
var children = firebase.database().ref('Success/').onWrite(event => {
return event.data.ref.parent.once("value", (snapshot) => {
const count = snapshot.numChildren();
console.log(count);
})
})
Where might I be going wrong.
As explained in the doc, you have to use the numChildren() method, as follows:
var ref = firebase.database().ref("Success");
ref.once("value")
.then(function(snapshot) {
console.log(snapshot.numChildren());
});
If you want to use this method in a Cloud Function, you can do as follows:
exports.children = functions.database
.ref('/Success')
.onWrite((change, context) => {
console.log(change.after.numChildren());
return null;
});
Note that:
The new syntax for Cloud Functions version > 1.0 is used, see https://firebase.google.com/docs/functions/beta-v1-diff?authuser=0
You should not forget to return a promise or a value to indicate to the platform that the Cloud Function execution is completed (for more details on this point, you may watch the 3 videos about "JavaScript Promises" from the Firebase video series: https://firebase.google.com/docs/functions/video-series/).
const db = getDatabase(app)
const questionsRef = ref(db, 'questions')
const mathematicalLiteracy = child(questionsRef, 'mathematicalLiteracy')
onValue(mathematicalLiteracy, (snapshot) => {
const data = snapshot.val()
const lenML = data.length - 1
console.log(lenML)
})
This method worked for me. I wanted to get the children's count of the mathematicalLiteracy node in my database tree. If I get its value using .val() it returns an array that contains that node's children and an extra empty item. So, I subtracted that one empty item's count. Finally, I get my needed children's count.