So I have a collection in firebase and want all the documents populated in the table dynamically. At the moment, it just populates the last document onto the table even after using the spread operator. Somebody help me with a solution to this. Thank you.
Here is the code:
import React, { useEffect, useState } from "react";
import { collection, getDocs } from "firebase/firestore";
import { db } from "../../firebase/firebase";
import { DataGrid } from "@mui/x-data-grid";
const columns = [
{ field: "name", headerName: "Name", width: 160 },
{ field: "email", headerName: "Email", width: 210 },
{ field: "roles", headerName: "Roles", width: 160 },
{ field: "isSuspended", headerName: "Suspended", width: 130 },
{ field: "lastUpdated", headerName: "Last Updated", width: 150 },
{ field: "updatedByEmail", headerName: "Updated By", width: 150 },
];
export default function Admins() {
const [row, setRow] = useState([]);
useEffect(() => {
const getAdmins = async () => {
const admins = await getDocs(collection(db, "admins"));
admins.forEach((admin) => {
console.log(admin.data());
setRow([
...row,
{
id: admin.data().email,
name: admin.data().name,
email: admin.data().email,
roles: admin.data().roles,
isSuspended: admin.data().isSuspended,
lastUpdated: admin.data().lastUpdated,
updatedByEmail: admin.data().updatedByEmail,
},
]);
});
};
getAdmins();
}, []);
console.log("row", row);
return (
<div style={{ height: 400, width: "100%" }}>
<DataGrid
rows={row}
columns={columns}
pageSize={10}
rowsPerPageOptions={[10]}
checkboxSelection
/>
</div>
);
}
The reason this is happening is because the state doesn't update completely until the use effect is done. This means the state is the same as it was before the use effect ran. Here's how you can fix this:
Instead of using
setRow([
...row,
{
id: admin.data().email,
name: admin.data().name,
email: admin.data().email,
roles: admin.data().roles,
isSuspended: admin.data().isSuspended,
lastUpdated: admin.data().lastUpdated,
updatedByEmail: admin.data().updatedByEmail,
},
]);
Use
setRow((r) => ([
...r,
{
id: admin.data().email,
name: admin.data().name,
email: admin.data().email,
roles: admin.data().roles,
isSuspended: admin.data().isSuspended,
lastUpdated: admin.data().lastUpdated,
updatedByEmail: admin.data().updatedByEmail,
},
]));
By passing a function with the r
argument, react knows to pass the actual current state value to the function, which will just return something, and that will be put into state.