I'm making a todo list app using react
and firebase
realtime database.
I want to get the todos ordered by date.
My Database:
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());
});