I am using React Firebase hook to log in to my website. when trying to log in with the wrong email or password in the login form, an error message will be returned from the React firebase hook. But even after giving the wrong input, an error message is not returning
const Login = () => {
const [signInWithEmailAndPassword, error] =
useSignInWithEmailAndPassword(auth);
const location = useLocation();
const navigate = useNavigate();
const from = location?.state?.from?.pathname || '/';
if (error) {
return (
<div>
<p>Error: {error.message}</p>
</div>
);
}
const handleLogIn = (e) => {
e.preventDefault();
const email = e.target.email.value;
const password = e.target.password.value;
signInWithEmailAndPassword(email, password)
e.target.reset();
navigate(from, { replace: true })
}
CodePudding user response:
You are using signInWithEmailAndPassword
hook incorrectly.
signInWithEmailAndPassword
returns an array & 3th index is of error message.
You can follow this: https://github.com/CSFrequency/react-firebase-hooks/blob/master/auth/README.md#usesigninwithemailandpassword
const [
signInWithEmailAndPassword,
user,
loading,
error,
] = useSignInWithEmailAndPassword(auth);
Since, useSignInWithEmailAndPassword
returns an Array, We need to extract/destructure the value from respective index.
Apart from that, You must also use loading
to display whether firebase is still authorizing the request or not (Loading State).
CodePudding user response:
The signInWithEmailAndPassword
appears to be an async
function and your code isn't waiting for the returned Promise to resolve. I'm guessing you are seeing the navigate("/");
called and the app is navigating to the home page.
const handleLogIn = (e) => {
e.preventDefault();
const email = e.target.email.value;
const password = e.target.password.value;
signInWithEmailAndPassword(email, password); // <-- no waiting for promise
e.target.reset();
navigate(from, { replace: true }); // <-- navigate away
};
export default (auth: Auth): EmailAndPasswordActionHook => { const [error, setError] = useState<AuthError>(); const [loggedInUser, setLoggedInUser] = useState<UserCredential>(); const [loading, setLoading] = useState<boolean>(false); const signInWithEmailAndPassword = async ( email: string, password: string ) => { setLoading(true); setError(undefined); try { const user = await firebaseSignInWithEmailAndPassword( auth, email, password ); setLoggedInUser(user); } catch (err) { setError(err as AuthError); } finally { setLoading(false); } }; const resArray: EmailAndPasswordActionHook = [ signInWithEmailAndPassword, loggedInUser, loading, error, ]; return useMemo<EmailAndPasswordActionHook>(() => resArray, resArray); };
The handleLogin
handler should probably wait for the Promise to settle so any errors can be returned by the hook. It turns out though that signInWithEmailAndPassword
also doesn't return any resolve/rejected values, so there's no way to know the authentication was successful from within the handleLogIn
callback function, the component will need to use the hook's returned loading
and loggedInUser
states to determine if it is safe to navigate.
Example:
const Login = () => {
const [
signInWithEmailAndPassword,
loggedInUser,
loading,
error,
] = useSignInWithEmailAndPassword(auth);
const location = useLocation();
const navigate = useNavigate();
const from = location?.state?.from?.pathname || '/';
useEffect(() => {
if (!loading && loggedInUser) {
navigate(from, { replace: true });
}, [loggedInUser, loading, navigate, from]);
if (error) {
return (
<div>
<p>Error: {error.message}</p>
</div>
);
}
const handleLogIn = (e) => {
e.preventDefault();
const email = e.target.email.value;
const password = e.target.password.value;
signInWithEmailAndPassword(email, password)
e.target.reset();
}
...