admin 管理员组

文章数量: 1086019

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
Add a ment  | 

3 Answers 3

Reset to default 5

Okay, 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()));
    }); 
    }, []);

本文标签: javascriptHow to order documents in a collection in FirestoreStack Overflow