You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中useEffect实现登录成功后重定向至/panel路由失效问题

Fixing Login Redirect Issue in React App

Let's walk through why your redirect isn't working after successful login and how to fix it.

The Problem Breakdown

  1. LoginPage Redirect Trigger: Your useEffect in LoginPage only runs once when the component mounts. At that point, the token hasn't been saved to localStorage yet. When the login mutation completes and saves the token, this useEffect doesn't re-run (since it has an empty dependency array), so shouldRedirect never gets set to true.
  2. PrivateRoute Authentication Check: In your App.tsx, the token variable is only evaluated once when the App component initializes. After you log in and save the token, the App doesn't re-render, so the PrivateRoute still uses the initial (empty) token value to check authentication — meaning it'll redirect to 404 even if you try to navigate to /panel.

Step-by-Step Fixes

1. Update LoginPage to Trigger Redirect After Successful Login

Instead of relying on a useEffect that runs only once, we can directly trigger the redirect right after saving the token to localStorage using React Router's useHistory hook.

Here's the modified LoginPage code snippet:

import { useHistory } from 'react-router-dom'; // Add this import

function LoginPage (){ 
  const [state, setState] = useState({ email: '', password: '', }); 
  const [submitted, setSubmitted] = useState(false); 
  const history = useHistory(); // Initialize history hook

  function ShowError(){ 
    if (!localStorage.getItem('token')) { 
      console.log('Login Not Successful'); 
      return ( 
        <ThemeProvider theme={colortheme}> 
          <Typography color='primary'> Login Unsuccessful </Typography> 
        </ThemeProvider>
      ) 
    } 
  }

  function submitForm(LoginMutation: any) { 
    setSubmitted(true); 
    const { email, password } = state; 
    if(email && password){ 
      LoginMutation({ 
        variables: { email: email, password: password, }, 
      }).then(({ data }: any) => { 
        localStorage.setItem('token', data.loginEmail.accessToken);
        history.push('/panel'); // Trigger redirect here immediately after saving token
      }) 
      .catch(console.log) 
    } 
  }

  // Rest of your LoginPage code remains the same...
}

2. Fix PrivateRoute to Check Token Dynamically

We need to make sure the PrivateRoute checks for the token every time it renders, not just on App initialization. Here are two solid options:

Option A: Update PrivateRoute to Check Token on Render

const PrivateRoute = ({component, ...rest}: any) => { 
  const routeComponent = (props: any) => { 
    // Check token directly in the render function to get the latest value
    const isAuthenticated = !!localStorage.getItem('token');
    return isAuthenticated ? React.createElement(component, props) : <Redirect to={{pathname: '/404'}}/>; 
  }; 
  return <Route {...rest} render={routeComponent}/>; 
};

Option B: Add State and Storage Listener to App.tsx

If you prefer managing the token in component state (to trigger re-renders automatically), this setup listens for changes to localStorage:

import { useState, useEffect } from 'react';

export default function App() { 
  const [token, setToken] = useState(localStorage.getItem('token'));

  // Listen for external changes to localStorage (e.g., login from another tab)
  useEffect(() => {
    const handleStorageUpdate = () => {
      setToken(localStorage.getItem('token'));
    };
    window.addEventListener('storage', handleStorageUpdate);
    return () => window.removeEventListener('storage', handleStorageUpdate);
  }, []);

  return ( 
    <div> 
      <BrowserRouter> 
        <Switch> 
          <Route exact path='/' component= {HomePage}></Route> 
          <Route path='/login' component= {LoginPage}></Route> 
          <Route path='/404' component= {Error404Page}></Route> 
          <PrivateRoute path='/panel' isAuthenticated={!!token} component={PanelHomePage} /> 
          <Redirect from='*' to='/404' /> 
        </Switch> 
      </BrowserRouter> 
    </div> 
  ); 
}

Why This Works

  • Direct Redirect: By calling history.push('/panel') right after saving the token, we ensure the redirect happens immediately upon successful login, no waiting for state updates or effect triggers.
  • Dynamic Authentication Check: Either checking the token directly in PrivateRoute on each render, or having the App listen for storage changes, ensures the authentication status is always up-to-date when accessing the private /panel route.

内容的提问来源于stack exchange,提问作者user12541823

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 20:42:27