我正在开发一个 React 应用程序,使用 AWS Amplify 进行身份验证,使用 Ionic React 作为 UI。我的问题是来自react-router-dom的history.push方法,该方法在第一次单击成功登录后似乎不会重定向用户,但在第二次单击时有效。此行为发生在 LoginPage 组件中,在使用 Amplify 成功进行身份验证后,我尝试将用户重定向到主页。
这是我的登录函数和 LoginPage 组件中 useEffect 挂钩的简化版本:
import React, { useEffect, useState } from 'react';
import { useHistory } from 'react-router-dom';
import { Auth } from 'aws-amplify';
import { IonButton, IonInput, IonPage } from '@ionic/react';
const LoginPage = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const history = useHistory();
const login = async () => {
try {
const user = await Auth.signIn(email, password);
console.log('Login successful:', user);
history.push('/dashboard'); // Not redirecting on first click
} catch (error) {
console.error('Login failed:', error);
}
};
return (
<IonPage>
<IonInput value={email} onIonChange={e => setEmail(e.detail.value)} />
<IonInput type="password" value={password} onIonChange={e => setPassword(e.detail.value)} />
<IonButton onClick={login}>Login</IonButton>
</IonPage>
);
};
export default LoginPage;
我的主页:
import { Route, Redirect } from 'react-router-dom'
import { IonRouterOutlet } from '@ionic/react'
import { IonLabel, IonIcon, IonTabs, IonTabBar, IonTabButton } from '@ionic/react'
import { wallet, flash, list, documentTextOutline } from 'ionicons/icons'
import Dashboard from './tabs/DashboardTab'
import PrivateRoute from './auth/PrivateRoute'
import LoginPage from './LoginPage'
const HomePage = ({ match }) => {
return (
<IonTabs>
<IonRouterOutlet>
<Route path="/mobile/login" component={LoginPage} exact={true} />
<Route path="/mobile" render={() => <Redirect to="/mobile/dashboard" />} exact={true} />
<PrivateRoute path="/mobile/dashboard" component={Dashboard} exact={true} />
</IonRouterOutlet>
<IonTabBar slot="bottom">
<IonTabButton tab="tab1" href="/mobile/dashboard">
<IonIcon icon={flash} />
<IonLabel>Dashboard</IonLabel>
</IonTabButton>
</IonTabBar>
</IonTabs>
)
}
export default HomePage
私人路线:
import React, { useState, useEffect } from 'react'
import { Route, Redirect } from 'react-router-dom'
import { Auth } from 'aws-amplify'
import { IonSpinner } from '@ionic/react'
import { useLocation } from 'react-router-dom'
const PrivateRoute = ({ component: Component, render, ...rest }) => {
const [isLoggedIn, setIsLoggedIn] = useState(false)
const [checkingStatus, setCheckingStatus] = useState(true)
const [user, setUser] = useState(null)
const location = useLocation()
useEffect(() => {
checkAuthState()
}, [location])
async function checkAuthState() {
setCheckingStatus(true)
try {
const currentUser = await Auth.currentAuthenticatedUser()
setIsLoggedIn(true)
setUser(currentUser)
} catch (error) {
console.error('Not logged in', error)
setIsLoggedIn(false)
} finally {
setCheckingStatus(false)
}
}
return (
<Route
{...rest}
render={(props) =>
checkingStatus ? (
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh' }}>
<IonSpinner name="crescent" />
</div>
) : isLoggedIn ? (
render ? (
render({ ...props, user })
) : (
<Component {...props} user={user} />
)
) : (
<Redirect to="/mobile/login" />
)
}
/>
)
}
export default PrivateRoute
按照@Drew Reese 的建议,花了一些时间进行调试后,我发现重定向确实有效,但页面未正确呈现。或者更确切地说,我的路线设置方式似乎存在问题。
在研究我的 AppShell.js 时,我对路由配置进行了重要修改。最初,我使用常规来处理仪表板的重定向。然而,我意识到这种方法并没有在成功验证后触发所需的组件渲染。
这是我的 AppShell.js 的原始片段:
<IonApp>
<IonReactRouter>
<IonRouterOutlet id="main">
<Route path="/mobile" render={(props) => <HomePage {...props} />} />
<Route path="/" render={() => <Redirect to="/mobile/dashboard" />} exact={true} />
</IonRouterOutlet>
</IonReactRouter>
</IonApp>
为了解决这个问题,我将第二个更改为 . 此修改背后的目的是确保登录后的重定向逻辑封装在 中,从而确保我们的身份验证逻辑得到一致应用。这是修改后的配置:
<IonApp>
<IonReactRouter>
<IonRouterOutlet id="main">
<Route path="/mobile" render={(props) => <HomePage {...props} />} />
<PrivateRoute path="/" render={() => <Redirect to="/mobile/dashboard" />} exact={true} />
</IonRouterOutlet>
</IonReactRouter>
</IonApp>
此更改基于这样的理解:与标准不同,组件在呈现指定组件或重定向用户之前包含身份验证检查。通过应用这种方法,我能够确保仅在验证用户的身份验证状态后才将用户重定向到仪表板,解决了由于身份验证上下文中的路由处理不当而导致仪表板无法正确呈现的问题。
谢谢!