Home > Net >  React firebase database order by date
React firebase database order by date

Time:07-04

I'm making a todo list app using react and firebase realtime database.

I want to get the todos ordered by date.

My Database: photo

And if I cant do this from firebase, is there a way to order it from the client side (react)?

My Code

Todos.js:

import { useState, useEffect } from "react";
import { signOut, onAuthStateChanged } from "firebase/auth";
import { uid } from "uid";
import { set, ref, onValue } from "firebase/database";
import { auth, db } from "../firebase";
import moment from "moment";

function Todos() {
  const [todos, setTodos] = useState([]);
  const [newTodo, setNewTodo] = useState("");
  const navigate = useNavigate();

  useEffect(() => {
    auth.onAuthStateChanged((user) => {
      if (user) {
        onValue(ref(db, `/${auth.currentUser.uid}`), (snapshot) => {
          setTodos([]);
          const data = snapshot.val();
          if (data !== null) {
            Object.values(data).map((todo) => {
              setTodos((currentTodos) => [todo, ...currentTodos]);
            });
          }
        });
      } else {
        navigate("/");
      }
    });
  }, []);

  const handleSignOut = () => {
    signOut(auth)
      .then(() => navigate("/"))
      .catch((error) => alert(error.message));
  };

  const addTodo = () => {
    const uidd = uid();
    set(ref(db, `${auth.currentUser.uid}/${uidd}`), {
      task: newTodo,
      uid: uidd,
      createdAt: moment().format("YYYY-MM-DD k:m:s"),
    });

    setNewTodo("");
  };

  return (
    <>
      <Center>
        <Button colorScheme="red" marginTop={5} onClick={handleSignOut}>
          Logout
        </Button>
      </Center>
      <Container
        maxW="4xl"
        marginTop={8}
        display="flex"
        alignItems="center"
        justifyContent="center"
      >
        <Box
          boxShadow="base"
          rounded="lg"
          padding={10}
          background="white"
          width="100%"
        >
          <Heading as="h1" size="md" textAlign="center">
            Todo List App
          </Heading>
          <form onSubmit={(e) => e.preventDefault()}>
            <Box
              display="flex"
              alignItems="center"
              justifyContent="space-between"
              marginTop={5}
            >
              <Input
                placeholder="New Task"
                value={newTodo}
                onChange={(e) => setNewTodo(e.target.value)}
                size="lg"
                width="80%"
              />
              <Button
                colorScheme="teal"
                height={45}
                rightIcon={<MdAdd />}
                margin={0}
                onClick={addTodo}
                type="submit"
              >
                Add
              </Button>
            </Box>
          </form>
          {todos.map((todo, index) => {
            return <Todo key={index} task={todo.task} uid={todo.uid} />;
          })}
        </Box>
      </Container>
    </>
  );
}

export default Todos;

Thanks in advance.

CodePudding user response:

Since you are loading the TODOs for a single user, you can indeed order them by their createdAt property. To do this, use a query as shown in the documentation on ordering and filtering data:

const ref = ref(db, `/${auth.currentUser.uid}`);
const query = query(ref, orderByChild('createdAt'));
onValue(query, (snapshot) => {
  ...

Inside the code you'll then need to make sure to use snapshot.forEach to loop over the children in order, as calling .val() before that will return a JSON object and the properties in a JSON object are by definition not ordered:

snapshot.forEach((child) => {
  console.log(child.key, child.val());
});
  • Related