I have a problem, after the version 9 update of Firebase, I cant seem to figure out how to order the documents in a collection.
Here is my code. I do not seem to understand how to implement the orderBy in the onSnapshot. Can someone please nudge me in the right direction. I have looked through the documentation but could not find a solution.
import React, { useState, useEffect } from "react";
import SignOut from "./SignOut";
import { Grid, Typography, Avatar } from "@material-ui/core";
import db from "../firebase";
import { onSnapshot, collection, orderBy, query, limit } from "firebase/firestore";
import SendMessage from "./SendMessage";
function ChatBox() {
const [messages, setMessages] = useState([]);
useEffect(() => {
onSnapshot(collection(db, "messages"), (snapshot) => {
setMessages(snapshot.docs.map((doc) => doc.data()));
});
}, []);
return (
<>
<Grid container>
<Grid item xs="12" style={{ textAlign: "right" }}>
<SignOut></SignOut>
</Grid>
{messages.map(({ id, text, photoURL }) => (
<Grid item xs="12" key={id} style={{ marginBottom: "1rem" }}>
<Avatar alt="" src={photoURL} />
<Typography>{text}</Typography>
</Grid>
))}
</Grid>
<Grid container>
<SendMessage></SendMessage>
</Grid>
</>
);
}
export default ChatBox;
I have a problem, after the version 9 update of Firebase, I cant seem to figure out how to order the documents in a collection.
Here is my code. I do not seem to understand how to implement the orderBy in the onSnapshot. Can someone please nudge me in the right direction. I have looked through the documentation but could not find a solution.
import React, { useState, useEffect } from "react";
import SignOut from "./SignOut";
import { Grid, Typography, Avatar } from "@material-ui/core";
import db from "../firebase";
import { onSnapshot, collection, orderBy, query, limit } from "firebase/firestore";
import SendMessage from "./SendMessage";
function ChatBox() {
const [messages, setMessages] = useState([]);
useEffect(() => {
onSnapshot(collection(db, "messages"), (snapshot) => {
setMessages(snapshot.docs.map((doc) => doc.data()));
});
}, []);
return (
<>
<Grid container>
<Grid item xs="12" style={{ textAlign: "right" }}>
<SignOut></SignOut>
</Grid>
{messages.map(({ id, text, photoURL }) => (
<Grid item xs="12" key={id} style={{ marginBottom: "1rem" }}>
<Avatar alt="" src={photoURL} />
<Typography>{text}</Typography>
</Grid>
))}
</Grid>
<Grid container>
<SendMessage></SendMessage>
</Grid>
</>
);
}
export default ChatBox;
Share
Improve this question
edited Sep 22, 2021 at 12:34
Renaud Tarnec
83.2k10 gold badges98 silver badges129 bronze badges
Recognized by Google Cloud Collective
asked Sep 22, 2021 at 11:21
Franco LabuschagneFranco Labuschagne
891 silver badge8 bronze badges
0
3 Answers
Reset to default 5Okay, I found a solution:
When you use the order by, if the field you are trying to order the documents by does not excist in the document, the order by will not "store" and order that document. Next, in my chat application I created a field with the Timestamp
constructor that Firebase offers. That allowed me to order the documents in the createdAt
order.
My code for the ChatBox file: Chatbox.js
import { collection, query, onSnapshot, orderBy } from "firebase/firestore";
//OTHER CODE
useEffect(() => {
onSnapshot(query(collection(db, "messages"), orderBy("createdAt")), (snapshot) => {
setMessages(snapshot.docs.map((doc) => doc.data()));
});
}, []);
SendMessage.js
import { collection, addDoc, Timestamp } from "firebase/firestore";
//OTHER CODE
const [userMessage, setUserMessage] = useState("");
async function sendUserMessage(e) {
const auth = getAuth();
e.preventDefault();
const { uid, photoURL } = auth.currentUser;
await addDoc(collection(db, "messages"), {
text: userMessage,
photoURL,
uid,
createdAt: Timestamp.fromDate(new Date()),
});
}
Hope this makes sense.
In JS API v9 we have to perform everything in a functional way. To order the collection before you attach a listener, you need to perform a query. A query can take a reference, order the results and pass the results to the caller.
In other words, your code should look like this:
import { onSnapshot, collection, orderBy, query, limit } from "firebase/firestore";
//OTHER CODE
useEffect(() => {
onSnapshot(query(collection(db, "messages"), orderBy("YOUR_FIELD")), (snapshot) => {
setMessages(snapshot.docs.map((doc) => doc.data()));
});
}, []);
Change YOUR_FIELD with the reference to any field you want to use to order the results. What we are doing here is:
- getting a reference to a collection
- asking firestore to perform a query on that collection, ordering the results by a field
- attaching a listener to the results
Hi can you can try this :
useEffect(() => {
onSnapshot(query(collection(db, "messages").orderBy('createdAt').startAfter(today)),
(snapshot) => {
setMessages(snapshot.docs.map((doc) => doc.data()));
});
}, []);