I have a dashboard.js file which is supposed to render information about user from firebase database. I want to loop over this fetched data, find user which email matches my currentUser.email state (kinda not the best practice) I dont know how to assign this found user to a state (it runs endlessly) so I can render entire dashboard so: first name, username, profile image.
img: thats what i get in console, and want it accessible in entire scope
So if you take a look at this screenshot i want my dashboard to look like this:
-email:newadmin@gmail.com
-name:Joe Black
- and profile picture
this is supossed to be a profile page so i will add bio and more things, i basically want this database to be fully accessible here based on email which i pass between components, users login via email
const Dashboard = () => {
const [error, setError] = useState("");
const { setcurrentUser, currentUser, logout, email } = useContext(UserProvider);
const navigate = useNavigate();
const handleLogOut = async () => {
setError("");
try {
await logout();
navigate("/login");
} catch (err) {
setError(err);
}
};
auth.onAuthStateChanged((currentUser) => {
if (currentUser) {
setcurrentUser(currentUser);
}
});
const url = "https://skitter-9e5e3-default-rtdb.europe-west1.firebasedatabase.app/users.json";
const [emailstate, setEmailstate] = useState();
const byEmail = async () => {
const response = await fetch(url);
const data = await response.json();
for (let i = 0; i <= Object.keys(data).length; i++) {
if (data[Object.keys(data)[i]].email == currentUser.email) {
console.log(data[Object.keys(data)[i]]);
}
}
};
byEmail();
return (
<>
<Card>
<Card.Body>
<span className="text-center">
<strong>Email: {currentUser.email}</strong>
</span>
</Card.Body>
</Card>
<div>
<Button variant="link" onClick={handleLogOut}>
Log out
</Button>
</div>
</>
);
};
export default Dashboard;
Use an effect hook so that the fetch request only runs once, rather than every time the component runs. You should do the same for the onAuthStateChanged - you only need to add one listener, not one listener for every time the component's been rendered.
When you find a matching item in the response, set it to a state variable. In a for loop, don't start with 0 and use i <= arr.length - that'll iterate once more than the length of the array. End at the last index of the array with i < arr.length instead - or avoid manual iteration entirely and use find instead.
const [userData, setUserData] = useState();
useEffect(() => {
auth.onAuthStateChanged(setcurrentUser);
const url = "https://skitter-9e5e3-default-rtdb.europe-west1.firebasedatabase.app/users.json";
fetch(url)
.then(response => response.json())
.then((data) => {
const currentUserObj = Object.values(data).find(obj => obj.email === currentUser?.email);
if (currentUserObj) {
setUserData(currentUserObj);
}
})
.catch(handleErrors); // don't forget this part - don't ignore errors
}, []);
Then the userData state will contain the object from the API, if one was found.