I am using an array and useState()
to fetch the data from the firebase database. The array is initially empty. However after I recieve the data from the firebase after its initial loading and try to forward the data to other component usig props for rendering it, the initial empty array is forwarded. I used useEffect()
with the loading
(from useAuthState()
) to fetch the data once the firebase is done loading.
Here’s my code
User Component
import { useEffect, useState } from "react";
import { auth, db } from "../firebaseConfig";
import { useNavigate } from "react-router-dom";
import { useAuthState } from "react-firebase-hooks/auth";
import { CircularProgress } from "@mui/material";
import UserDataTable from "../Components/User-data-table/UserDataTable";
function User() {
const [userData, setUserData] = useState([]);
const [user, loading] = useAuthState(auth);
const navigate = useNavigate();
const fetchUserData = () => {
const resultsReference = db.collection("Results");
const { uid } = auth.currentUser;
let tempData = [];
resultsReference
.where("userId", "==", uid)
.get()
.then((snapshot) => {
snapshot.docs.forEach((doc) => {
tempData.push({ ...doc.data() });
});
setUserData(tempData);
});
};
const effectFunction = async () => {
if (loading) {
return <CircularProgress />;
}
};
useEffect(() => {
if (!loading) {
fetchUserData();
}
if (!loading && !user) {
navigate("/");
}
effectFunction();
}, [loading]);
return (
<div>
<UserDataTable userData={userData} />
</div>
);
}
export default User;
UserDataTable Component
import {
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
} from "@mui/material";
import "./UserDataTable.scss";
import { useMyTheme } from "../../Context/ThemeContext";
function UserDataTable({ userData }) {
const { theme } = useMyTheme();
const tableStyles = {
color: theme.textColor,
fontFamily: ["Kode Mono", "monospace"].join(","),
textAlign: "center",
fontSize: "2rem",
};
return (
<div className="user-table">
<TableContainer>
<Table>
<TableHead>
<TableRow>
<TableCell style={tableStyles}>WPM</TableCell>
<TableCell style={tableStyles}>Raw WPM</TableCell>
<TableCell style={tableStyles}>Accuracy</TableCell>
<TableCell style={tableStyles}>Characters</TableCell>
<TableCell style={tableStyles}>Date</TableCell>
</TableRow>
</TableHead>
<TableBody>
{userData.map((d) => { **// Since the prop is empty i am unable to render it here !**
<TableRow>
<TableCell>{d.wpm}</TableCell>
<TableCell>{d.rawWpm}</TableCell>
<TableCell>{d.accuracy}</TableCell>
<TableCell>0|0|0|0</TableCell>
<TableCell>{d.timeStamp.toDate().toLocaleString()}</TableCell>
</TableRow>;
})}
</TableBody>
</Table>
</TableContainer>
</div>
);
}
export default UserDataTable;
I think this might be a problem when using useEffect() as when the component reloads, the empty array is being forwarded to the next component. I am new to react and was following a tutorial however the instructor did not face this issue. Please Help
I also think that the data is being forwarded to the next component. But the component processes the empty array first and then it never processes the non empty array. How do I fix this.
When consoling the data, first empty array, then filled arrays are observed:
2
Answers
Since you initialize the state to an empty array here
const [userData, setUserData] = useState([]);
, that’ll be the initial state with which yourUserDataTable
is rendered.Your
UserDataTable
code will either need to handle that initial state, or yourUser
will need to only render theUserDataTable
component when the data has been loaded.Your state update code and passing as props is fine, but you have a couple logical issues.
The
useEffect
hook can’ calleffectFunction
and render the loading UI,CircularProgress
must be rendered as part of the render return of theUser
component.The
UserDataTable
must return a value when mapping the row data. The arrow function body is missing a return statement returning the row JSX. Your table UI isn’t working because no rows are rendered.Use an explicit return from the function body:
Use an implicit return without a function body, e.g. direct return:
The initially empty
userData
array is passed toUserDataTable
, and when the state updates, the updateduserData
state is passed as a prop andUserDataTable
will rerender.