When I'm trying to use hook useUserData
to save and display user data in the project even after I reload the page, but I have an error TypeError: Cannot destructure property 'email' of '(0 , _hooks_useUserData__WEBPACK_IMPORTED_MODULE_13__.useUserData)(...)' as it is undefined
. I was advised to use the useUserData
hook in this question but I get an error that we could not solve. All imports
and exports
are correct. What am I doing wrong? Maybe other solutions can be used here?
This is my codesandbox template, where I use this hook
CodePudding user response:
Well, you are expecting that onSnapshot
will magically be called right after you app loads - it needs some time to fetch document from your collection. I would add additional flag which indicate if data is still loading or not:
function useUserData(userId) {
const [userData, setUserData] = useState(undefined);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
if (!userId) return; // null or undefined is passed, so just do nothing
const unsubscribe = onSnapshot(doc(db, "users", userId), (doc) => {
setIsLoading(false);
if (doc.exists()) {
setUserData(doc.data()); // found and setting a user
} else {
setUserData(null); // null means user not found in users collection
}
});
return () => unsubscribe();
}, [userId]);
return { userData, isLoading };
}
Then use it like that:
function Profile({ uid }) {
const { isLoading, userData } = useUserData(uid);
if (isLoading) {
return <span>Loading...</span>;
}
if (!userData) {
return <span>Ooops. Profile not found</span>;
}
return <span>{userData.firstName}</span>
}
In addition you are not actually saving anything after successful signup, it should be like that (the same with email password):
const googleSignIn = async () => {
const provider = new GoogleAuthProvider();
const userCredential = await signInWithPopup(auth, provider)
const user = userCredential.user;
const uid = user.uid;
await setDoc(doc(db, "users", uid), {
...data
});
};