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

React Router:登录后跳转原受限路由及回退两页并保留历史

Alright, let's tackle your two React Router challenges here—redirecting back to the protected route after login, and safely navigating back two pages while preserving history. I'll also fix up your existing verifyOTP action code to integrate these solutions.

Solution for Protected Route Redirect & History Navigation in React Router

1. Preserving the Original Protected Route for Post-Login Redirect

When a user tries to access a protected route like /account/dashboard without being logged in, we need to save that original path first so we can send them back there after successful authentication.

  • Step 1: Store the original path in your protected route guard
    Use React Router's Navigate component to pass the current location as state to the login page:

    // Inside your ProtectedRoute component
    import { Navigate, useLocation } from 'react-router-dom';
    
    const ProtectedRoute = ({ children }) => {
      const { isSignedIn } = useSelector(state => state.user);
      const location = useLocation();
    
      if (!isSignedIn) {
        // Send the user to login, and save the original path in state
        return <Navigate to="/login" state={{ from: location }} />;
      }
    
      return children;
    };
    
  • Step 2: Pass the saved path to your verifyOTP action
    In your login/OTP verification component, grab the saved path from location state and pass it to the action:

    // Inside VerifyOTP component
    const location = useLocation();
    const redirectFrom = location.state?.from?.pathname || '/'; // Fallback to homepage
    
    // When triggering OTP verification
    dispatch(verifyOTP(enteredOTP, redirectFrom));
    

2. Safely Navigating Back Two Pages (With History Preservation)

Your original code uses window.history.go(-2), which works, but we should add a safety check to avoid errors if there aren't enough pages in the history stack. Also, if you're using React Router v6, you'll want to use the navigate function instead of the legacy history object.

3. Updated verifyOTP Action Code

Here's the revised action with both solutions integrated, plus cleaner async/await syntax and a fix for a typo (verfied → verified):

export const verifyOTP = (data, redirectFrom) => async (dispatch, getState) => {
  const { userId, profileCompleted } = getState().user;
  
  try {
    const response = await svysh.post(`/customer/verify-otp/${userId}`, { 
      otp: Number(data) 
    });

    // Extract response data with clearer logic
    const verified = !response.data.error;
    const token = verified ? response.data.data.access_token : null;
    const tokenExpiry = verified ? Date.parse(response.data.data.expires_at) : null;
    const isSignedIn = !!token;
    const errorCode = response.data.error ? response.data.code : null;

    dispatch({
      type: actionTypes.VERIFY_OTP,
      accessToken: token,
      accessTokenExpiry: tokenExpiry,
      verified: verified, // Fixed typo from "verfied"
      isSignedIn: isSignedIn,
      error: response.data.error,
      errorCode: errorCode,
      message: response.data.message
    });
    dispatch(setLoading(false));

    if (verified) {
      if (!profileCompleted) {
        // Send user to complete profile first
        history.push('/complete-profile');
      } else {
        // Prioritize redirecting back to the original protected route
        if (redirectFrom) {
          history.push(redirectFrom);
        } else {
          // Fallback: go back two pages, with safety check
          if (window.history.length >= 3) {
            // Ensure we have enough history entries to go back 2 pages
            history.go(-2);
          } else {
            // If not, redirect to homepage as a fallback
            history.push('/');
          }
        }
      }
    } else {
      // OTP failed, send back to verification page
      history.push('/verify');
    }
  } catch (error) {
    console.log('Catch Error', error);
    dispatch(setLoading(false));
  }
};

Key Improvements:

  • Protected route redirect: We now prioritize sending the user back to their original intended route after successful login/OTP verification.
  • Safety for back navigation: Added a check to ensure we don't try to go back more pages than exist in the history stack.
  • Cleaner code: Swapped .then/.catch for async/await for better readability, fixed a typo in the action payload, and simplified response data extraction.
  • Fallback logic: Added a homepage fallback for cases where there's no saved redirect path or insufficient history entries.

For React Router v6 Users:

If you're using React Router v6, replace the history object with the navigate function from useNavigate():

  1. Pass navigate as an additional parameter to your action from the component.
  2. Replace history.push(path) with navigate(path) and history.go(-2) with navigate(-2).

Example component usage for v6:

import { useNavigate, useLocation } from 'react-router-dom';

const VerifyOTP = () => {
  const navigate = useNavigate();
  const location = useLocation();
  const redirectFrom = location.state?.from?.pathname || '/';

  const handleVerify = (otp) => {
    dispatch(verifyOTP(otp, redirectFrom, navigate));
  };

  // ... rest of component
};

Then update the action to use navigate instead of history:

export const verifyOTP = (data, redirectFrom, navigate) => async (dispatch, getState) => {
  // ... existing logic
  if (verified) {
    if (!profileCompleted) {
      navigate('/complete-profile');
    } else {
      if (redirectFrom) {
        navigate(redirectFrom);
      } else {
        if (window.history.length >= 3) {
          navigate(-2);
        } else {
          navigate('/');
        }
      }
    }
  } else {
    navigate('/verify');
  }
  // ... rest of logic
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:05:19