当用户通过谷歌身份验证(
onAuthStateChanged
)进行身份验证时,有时未加载根路径的正确组件,我会得到一个空白页面。
我正在尝试根据
"/"
的状态在user
路线中加载不同的组件:
<Login />
= 未经过身份验证
<Home />
= user.role
是用户
<Admin />
= user.role
是管理员
我尝试在 Login.jsx 文件和 AuthContext.jsx 文件中添加
<Navigate to="/" replace />
。我已经尝试添加 location.reload()
调用,但它导致了无限循环。
我知道当我设置状态(
setUser
)时,状态更改是异步的,只有在下一次渲染时 React 才会更新它。
当我将
console.log
语句放入代码中(用于调试)时,它工作得很好。
此外,如果我手动刷新页面(当页面为空白时),正确的组件会加载得很好。
在身份验证状态更改后通过 React Router 6 重新渲染根组件的最佳实践是什么?
AuthContext.jsx
import { useState, useEffect, createContext } from "react";
import { auth } from "./firebaseInit";
export const AuthContext = createContext();
export const AuthContextProvider = ({children}) => {
const [user, setUser] = useState(null);
useEffect( () => {
const unsubscribe = auth.onAuthStateChanged( async (auth_user) => {
if (auth_user) {
if (auth_user.emailVerified) {
// api call to grab user data
setUser(auth_user);
// SHOULD I PUT THIS HERE?
// return <Navigate to="/" replace />
}
}
});
return () => {
unsubscribe();
}
}, []);
return (
<AuthContext.Provider
value={{user}}
>
{children}
</AuthContext.Provider>
);
};
登录.jsx
import { Navigate } from "react-router-dom";
import { signInWithEmailAndPassword } from "firebase/auth";
import { auth } from "../../backend/firebaseInit";
export default function Login() {
const handleSubmit = async (e) => {
e.preventDefault();
const data = new FormData(e.currentTarget);
signInWithEmailAndPassword(auth, data.get('email'), data.get('password') )
.then( async (userCredential) => {
const auth_user = userCredential.user;
if (auth_user) {
// ADDING THIS MAKES IT WORK
//console.log('i am about to navigate');
// SHOULD I PUT THIS HERE?
//return <Navigate to="/" replace />;
}
})
.catch((err) => {
console.log(err.toString());
})
};
return (
<Container >
<Box>
// login form
</Box>
</Container>
);
}
路由.jsx
import { AuthContext } from './AuthContext';
import { useContext } from 'react';
import { BrowserRouter, Routes, Route } from'react-router-dom';
export default function ConvuRouter() {
const {user} = useContext(AuthContext);
return (
<BrowserRouter>
<Routes>
<Route path="/" element={user ? ( user.role === 'admin' ? <Admin /> : (user.role === 'user' ? <Home /> : <Login /> ) ) : <Login /> } />
</Routes>
</BrowserRouter>
);
};
问题可能是user.role尚未更新;当您导航到“/”时,您可以尝试添加加载状态,它将指示身份验证过程是否仍在进行中。如果是,您可以选择渲染加载微调器。