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

React应用中间层服务类如何编程导航至自定义错误页面?

在React Router v6的工具函数中处理重定向

首先明确:直接在非组件的工具函数里调用useNavigate或redirect是行不通的,原因如下:

  • useNavigate是React Hook,必须在组件或自定义Hook的顶层调用,不能在异步回调、普通函数中使用;
  • redirect是React Router专为路由的loader/action设计的API,它会抛出一个路由响应对象,只有路由系统能捕获并处理,普通异步函数里调用不会触发跳转。

下面是几种可行的解决方案:

方案1:将navigate函数作为参数传入工具方法

这是最直接的实现方式,组件中通过useNavigate拿到导航函数,传递给sendLoginRequest,在错误回调中直接调用:

修改sendLoginRequest:

import { NavigateFunction } from "react-router-dom";

export const sendLoginRequest = async (
  email: string,
  password: string,
  navigate: NavigateFunction // 新增参数
): Promise<string> => {
  return axiosApiUnauthorized.post(_getLoginEndpoint(), { email, password })
    .then(resp => resp.data.token)
    .catch(err => {
      console.log('err');
      navigate('/error'); // 直接调用导航
      throw err; // 抛出错误,让组件侧可以处理后续逻辑
    });
};

在Login组件中调用:

import { useNavigate } from "react-router-dom";

const Login = () => {
  const navigate = useNavigate(); // 获取navigate函数

  const onSubmitForm = async (formValue: any) => {
    try {
      const accessToken: string = await sendLoginRequest(
        formValue.email, 
        formValue.password,
        navigate // 传入navigate
      );
      storeToken('/', 'access_token', accessToken);
      const userInfo: UserInfo = fetchUserInfo();
      dispatch(userInfoAction.saveUserInfo(userInfo));
      navigate('/');
    } catch (err) {
      // 可选:组件侧额外处理错误
    }
  };

  // ... 其他组件逻辑
};

方案2:创建全局导航工具(基于Context)

如果不想每次调用都传递navigate,可以通过React Context把导航函数全局共享:

1. 创建导航Context:

// src/context/NavigationContext.tsx
import { createContext, useContext, useNavigate, NavigateFunction } from "react-router-dom";

const NavigationContext = createContext<NavigateFunction | undefined>(undefined);

export const NavigationProvider = ({ children }: { children: React.ReactNode }) => {
  const navigate = useNavigate();
  return (
    <NavigationContext.Provider value={navigate}>
      {children}
    </NavigationContext.Provider>
  );
};

// 自定义Hook,用于获取导航函数
export const useNavigation = () => {
  const navigate = useContext(NavigationContext);
  if (!navigate) {
    throw new Error('useNavigation must be used within a NavigationProvider');
  }
  return navigate;
};

2. 在App根组件中包裹Provider:

// src/App.tsx
import { NavigationProvider } from './context/NavigationContext';
import { RouterProvider, createBrowserRouter } from 'react-router-dom';

const router = createBrowserRouter([/* 路由配置 */]);

function App() {
  return (
    <NavigationProvider>
      <RouterProvider router={router} />
    </NavigationProvider>
  );
}

3. 在工具函数中使用(需在React组件树调用链中):

// 用自定义Hook包装请求逻辑
import { useNavigation } from './context/NavigationContext';

export const useLoginRequest = () => {
  const navigate = useNavigation();

  const sendLoginRequest = async (email: string, password: string): Promise<string> => {
    return axiosApiUnauthorized.post(_getLoginEndpoint(), { email, password })
      .then(resp => resp.data.token)
      .catch(err => {
        console.log('err');
        navigate('/error');
        throw err;
      });
  };

  return { sendLoginRequest };
};

在Login组件中使用:

const Login = () => {
  const { sendLoginRequest } = useLoginRequest();

  const onSubmitForm = async (formValue: any) => {
    try {
      const accessToken = await sendLoginRequest(formValue.email, formValue.password);
      // ... 后续逻辑
    } catch (err) {
      // 错误处理
    }
  };
};

方案3:使用Router实例的导航方法(无上下文依赖)

如果项目用createBrowserRouter创建路由,可以直接拿到router实例,调用其navigate方法,这种方式可在任何地方(包括纯工具函数)使用:

1. 定义全局Router实例:

// src/router.ts
import { createBrowserRouter } from 'react-router-dom';

export const router = createBrowserRouter([
  // 你的路由配置
]);

2. 在工具函数中直接使用:

import { router } from './router';

export const sendLoginRequest = async (email: string, password: string): Promise<string> => {
  return axiosApiUnauthorized.post(_getLoginEndpoint(), { email, password })
    .then(resp => resp.data.token)
    .catch(err => {
      console.log('err');
      router.navigate('/error'); // 直接调用router的navigate
      throw err;
    });
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 22:33:27