ReactJS使用Firebase邮箱密码认证时登录页加载跳转报错问题
问题修复方案
根因分析
- 核心错误:
Login和DashBoard组件中直接返回history.push()的执行结果,该方法返回值为undefined,违反React组件必须返回JSX或null的规则,触发渲染返回空的报错。 - 附加问题1:
AuthProvider未添加加载状态,Firebase的onAuthStateChanged是异步接口,初始加载阶段会先以currentUser = null渲染组件,等身份校验完成才更新用户状态,导致路由跳转逻辑提前误判。 - 附加问题2:
App.js中引用Dashboard组件时大小写不匹配,导入命名为DashBoard,路由中写的是Dashboard,会触发组件找不到的报错。 - 附加问题3:
Login.js中错误捕获的字段拼写错误,error.massage应为error.message。
修复步骤
1. 调整Auth.js,添加全局加载状态
import React, { useState, useEffect} from "react"; import { auth } from './config' import { onAuthStateChanged } from "firebase/auth"; export const AuthContext = React.createContext(); export const AuthProvider = ({ children }) => { const [currentUser, setCurrentUser] = useState(null); // 新增加载状态,标记是否完成Firebase身份校验 const [authLoading, setAuthLoading] = useState(true); useEffect(() => { const unsub = onAuthStateChanged(auth, (user) => { setCurrentUser(user); setAuthLoading(false); }) // 组件卸载时取消订阅,避免内存泄漏 return unsub }, []) // 校验完成前渲染加载占位,避免提前执行路由判断 if(authLoading) return <div>加载中...</div> return ( <AuthContext.Provider value={{currentUser, authLoading}}> {children} </AuthContext.Provider> ) }
2. 修复Login.js的跳转逻辑
将直接返回history.push改为先执行跳转,再返回null,避免返回undefined:
import React, {useContext ,useState } from "react"; import Form from "react-bootstrap/Form"; import Button from "react-bootstrap/Button"; import "./Login.css"; import { auth } from './config' import { signInWithEmailAndPassword } from "firebase/auth"; import { AuthContext } from "./Auth"; import { useHistory } from "react-router-dom"; const Login = () => { let history = useHistory(); const currentUser = useContext(AuthContext); const handleSubmit = (event) => { event.preventDefault(); const { email, password } = event.target.elements; signInWithEmailAndPassword(auth, email.value, password.value) .then((userCredential) => { const user = userCredential.user; console.log(user.uid); }) .catch((error) => { // 修复拼写错误 console.log(error.message); }); } if(currentUser) { // 先执行跳转,再返回null符合React渲染规则 history.push('/dashboard'); return null } return ( <div className="Login"> <h1>Login</h1> <Form onSubmit={handleSubmit}> {/* 补充你的表单控件即可 */} </Form> </div> ); } export default Login
3. 修复DashBoard.js的跳转逻辑
import React, {useContext} from 'react' import { AuthContext } from './Auth' import { auth } from './config' import { signOut } from 'firebase/auth' import { useHistory } from "react-router-dom"; const DashBoard = () => { const currentUser = useContext(AuthContext); let history = useHistory(); if(!currentUser) { history.push('/login'); return null } const signOutFunc = () => { signOut(auth) } return ( <div> <div className='container mt-5'> <h1>Welcome</h1> <h2>If you see this you are logged in.</h2> <button className='btn btn-danger' onClick={signOutFunc}>Sign Out</button> </div> </div> ) } export default DashBoard;
4. 修复App.js的组件命名大小写问题
import { BrowserRouter as Router, Route, Switch} from 'react-router-dom' import Login from './Login' import DashBoard from './DashBoard'; import { AuthProvider } from './Auth' function App() { return ( <AuthProvider> <Router> <Switch> <Route exact path="/login" component={Login} /> {/* 修复组件命名大小写,和导入的DashBoard保持一致 */} <Route exact path="/dashboard" component={DashBoard} /> </Switch> </Router> </AuthProvider> ); } export default App;
内容的提问来源于stack exchange,提问作者Na Lin
相关产品推荐
相关产品推荐

