React Router PrivateRoute结合Firebase Auth登录后持续重定向到登录页问题
问题根源
你现在的问题主要是两个核心错误:
- PrivateRoute里没有用你已经写好的AuthContext的
currentUser做判断,反而用了全局变量Cuser,这个变量只会在Signup组件渲染的时候才会被赋值,路由切换的时候根本不会同步更新,而且初始值是null,页面刚加载的时候直接就跳转到登录页了 - 没有处理Firebase Auth的初始化加载状态:Firebase初始化验证用户登录状态是异步的,在这个加载间隙
currentUser是undefined,这时候你直接判断未登录就跳转,当然会出问题
修复步骤
- 第一步:修改你的PrivateRoute组件,删掉没用的全局变量Cuser,增加加载状态判断:
const PrivateRoute = ({component: Component, ...rest}) => { const {currentUser} = useAuth() // 新增加载状态,currentUser为undefined时说明还在加载firebase auth状态,暂时不跳转 const [isLoading, setIsLoading] = useState(true) useEffect(() => { // 等currentUser状态确定后(不管是已登录还是未登录),再结束加载 setIsLoading(false) }, [currentUser]) if (isLoading) { // 加载期间可以显示自定义加载提示,避免页面闪跳 return <div>加载中...</div> } return ( <Route {...rest} render={props => { return currentUser ? <Component {...props} /> : <Redirect to="/signin" /> }} /> ) }
- 第二步:修复Signup组件的问题,给useEffect加空依赖数组避免重复监听,删掉没用的Cuser赋值:
const Signup = () => { const {history} = useHistory() const [user, setUser] = useState(null) // 加空依赖数组,只在组件挂载时监听一次登录状态 useEffect(() => { const authOberver = firebase.auth().onAuthStateChanged((user) => { setUser(user) if (user) { axios.post("http://localhost:4000/notes", { email: user.email, }) // 登录成功后直接跳首页,不需要依赖全局变量 history.push('/') } }); return authOberver }, [history]) return ( <> <div>Signin / Register</div> <StyledFirebaseAuth uiConfig={uiconfig} firebaseAuth={firebase.auth()}></StyledFirebaseAuth> </> ) }
- 第三步:确认根组件已经包裹了
AuthProvider,否则useAuth拿不到上下文状态:
// 以App.js为例 import { AuthProvider } from './context/AuthContext' function App() { return ( <AuthProvider> {/* 所有路由、组件都要放在AuthProvider内部 */} <Router> <Switch> <Route path="/signin" component={Signup} /> <PrivateRoute path="/" exact component={Home} /> </Switch> </Router> </AuthProvider> ) }
内容的提问来源于stack exchange,提问作者Tej
相关产品推荐
相关产品推荐

