javascript - history.push() 不能在 firebase 的身份验证中使用 react
问题描述
我正在使用 react、firebase auth 和 context api 构建身份验证。
登录.js
import React, { useEffect, useState } from 'react';
import { Form, Button, Container, Card } from 'react-bootstrap';
import { useAuth } from '../contextApi/contextApi';
import { Link } from 'react-router-dom';
import { useHistory } from 'react-router-dom';
function SignIn() {
let history = useHistory();
const { signIn } = useAuth();
const emailRef = React.useRef(null);
const passwordRef = React.useRef(null);
const [loading, setLoading] = useState(false);
let handleSubmit = async (e) => {
e.preventDefault();
console.log('connected');
try {
setLoading(true);
await signIn(emailRef.current.value, passwordRef.current.value);
console.log('push');
history.push('/dashboard');
} catch {
alert('handleSubmit went wrong!');
}
history.push('/dashboard');
setLoading(false);
};
return (
<div style={{ backgroundColor: '#a9a9a9' }}>
<Container
className="signin d-flex align-items-center justify-content-center"
style={{
minHeight: '100vh',
}}
>
<Card className="shadow">
<Card.Body>
<h2 className="text-center mb-4">Sign In</h2>
<Form onSubmit={handleSubmit}>
<Form.Group controlId="formBasicEmail">
<Form.Label>Email address</Form.Label>
<Form.Control
type="email"
placeholder="Enter email"
ref={emailRef}
required
/>
<Form.Text className="text-muted">
We'll never share your email with anyone else.
</Form.Text>
</Form.Group>
<Form.Group controlId="formBasicPassword">
<Form.Label>Password</Form.Label>
<Form.Control
type="password"
placeholder="Password"
ref={passwordRef}
required
/>
</Form.Group>
<Button variant="primary" type="submit" disabled={loading}>
Submit
</Button>
</Form>
<div className="w-100 text-center mt-2">
Need an account? <Link to="/signup">Sign up</Link>
</div>
<div className="w-100 text-center mt-2">
Forgot password? <Link to="/forgotpassword">Click here</Link>
</div>
<div className="w-100 text-center mt-2">
Back to <Link to="/">Home page</Link>
</div>
</Card.Body>
</Card>
</Container>
</div>
);
}
export default SignIn;
每当我成功登录时一切正常,但如果我稍后登录失败,即使我输入了正确的密码/电子邮件,登录页面也不会重定向到仪表板页面。
可以对我的代码的哪一部分错误进行一些说明吗?
contextApi.js
import React, { useContext, useEffect, useState } from 'react';
import { auth } from '../firebase';
import { useHistory } from 'react-router-dom';
const ContextApi = React.createContext();
export function useAuth() {
return useContext(ContextApi);
}
export const ContextApiProvider = ({ children }) => {
let [currentUser, setCurrentUser] = useState();
let [loading, setLoading] = useState(true);
useEffect(() => {
const unsubscribed = auth.onAuthStateChanged((user) => {
if (user) {
setCurrentUser(user);
setLoading(false);
} else {
setCurrentUser(null);
setLoading(false);
console.log(currentUser);
}
});
return unsubscribed;
}, []);
const signIn = (email, password) => {
auth.signInWithEmailAndPassword(email, password).catch(function (error) {
// Handle Errors here.
console.log(error);
let errorCode = error.code;
let errorMessage = error.message;
if (errorCode === 'auth/wrong-password') {
alert('sign in failed! Wrong password.');
} else if (!errorMessage) {
alert('you are signed in!');
} else {
alert(`sign in failed! ${errorMessage}`);
}
});
};
const signUp = (email, password) => {
auth.createUserWithEmailAndPassword(email, password).catch((error) => {
let errorCode = error.code;
let errorMessage = error.message;
console.log(errorMessage);
console.log(error);
console.log(errorCode);
if (errorCode === 'auth/weak-password') {
alert(`signup failed! The password is too weak!`);
} else if (!errorMessage) {
alert('signed up successfully');
} else {
alert(`sign up failed! ${errorMessage}`);
}
});
};
const resetPassword = (email) => {
auth.sendPasswordResetEmail(email).catch((error) => {
let errorCode = error.code;
let errorMessage = error.message;
if (errorCode === 'auth/invalid-email') {
alert('email not found');
} else {
alert(errorMessage);
}
});
};
const logout = () => {
return auth.signOut();
};
let value = {
signIn,
currentUser,
signUp,
resetPassword,
logout,
};
return (
<ContextApi.Provider value={value}>
{!loading && children}
{/* {children} */}
</ContextApi.Provider>
);
};
解决方案
您没有正确使用 firebase 功能,这里是您应该如何使用它的示例(来自文档)
const signIn = (email, password) => {
firebase.auth().signInWithEmailAndPassword(email, password)
.then((user) => {
// Signed in
//here you call history push (or a callback defined somone else)
// doc state that here we know that credentials was accepted
// while await means simply that the async code ended
// Then is better since you aren't blocking anything and it is more clean (most importantly people who maintain your code will have no issue)
// you will have no issue if firebase update something in thier lib ...
// history need to be defined before or passed as param
history.push('/dashboard')
// ...
})
.catch((error) => {
// nothing is required from you here (but you can for example show "forget password link)
var errorCode = error.code;
var errorMessage = error.message;
});
}
虽然 await 应该可以工作,但您无法确定用户是否已登录,上面的代码是另一种处理方式。
推荐阅读
- python - 消费者无法消费来自生产者的所有消息
- javascript - 歌剧浏览器上未调用 webrtc onicecandidate
- javascript - 如何使用 React.lazy 导入 Material UI 图标?
- python - 在 OpenGL 的 Python 包装器中获取缓冲区的值
- node.js - 使用在 Expo 中使用加密的第三方 npm 库
- javascript - 检测点击反应父组件外部
- git - 在 PyCharm 中推送提交的文件
- javascript - 我的 vue.js 代码从服务器重复获取数据
- javascript - 使用带有回调条件的 .join()
- python - 从给定的日期记录创建开始日期和结束日期的列