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

在createAsyncThunk的async函数中调用useNavigate无效且无报错,寻求帮助

问题原因

你直接在createAsyncThunk的回调函数里调用useNavigate是违反React Hook规则的——useNavigate是React Router提供的Hook,只能在函数组件的顶层代码或者自定义Hook中调用,不能在普通异步函数(比如thunk的payloadCreator)里使用。这就是代码没报错但导航完全无效的核心原因。

解决方案

下面提供三种可行的解决方式,你可以根据项目架构选择:

方式一:调用Thunk时传入navigate函数

修改Thunk,让它接收包含用户信息和navigate函数的参数对象:

import { createAsyncThunk } from '@reduxjs/toolkit';
import axios, { AxiosError } from 'axios';
import { toast } from 'react-toastify';
import { useNavigate } from 'react-router-dom';
import environment from '../path/to/environment';
import type { UserLoginProps } from '../types';

export const loginAdminUser = createAsyncThunk(
  'post/login',
  async ({ user, navigate }: { user: UserLoginProps; navigate: ReturnType<typeof useNavigate> }) => {
    try {
      const response = await axios.post(`${environment.BASE_URL}/user/admin-login`, user);
      console.log('response', response);

      if (response.data.success) {
        toast.success(response.data.message);
        toast('Redirecting to Home page');
        localStorage.setItem('token', response.data.data);
        // 调用传入的navigate函数
        navigate('/admin/home');
      } else {
        toast.error(response.data.message);
      }

      return response.data;
    } catch (error: unknown) {
      const err = error as AxiosError;
      throw new Error(err.message);
    }
  }
);

然后在组件中调用Thunk时,把useNavigate返回的函数传进去:

import { useDispatch } from 'react-redux';
import { useNavigate } from 'react-router-dom';
import { loginAdminUser } from '../path/to/thunk';
import type { UserLoginProps } from '../types';

function LoginComponent() {
  const dispatch = useDispatch();
  const navigate = useNavigate();

  const handleLogin = (userData: UserLoginProps) => {
    dispatch(loginAdminUser({ user: userData, navigate }));
  };

  // 组件渲染逻辑...
}

方式二:在组件中监听Thunk执行结果后导航

把导航逻辑从Thunk中剥离,放到组件里,通过监听Redux状态变化触发导航:
首先修改Thunk,移除导航相关代码,只处理API请求:

export const loginAdminUser = createAsyncThunk('post/login', async (user: UserLoginProps) => {
  try {
    const response = await axios.post(`${environment.BASE_URL}/user/admin-login`, user);
    console.log('response', response);

    if (response.data.success) {
      toast.success(response.data.message);
      toast('Redirecting to Home page');
      localStorage.setItem('token', response.data.data);
    } else {
      toast.error(response.data.message);
      // 抛出错误让Thunk进入rejected状态
      throw new Error(response.data.message);
    }

    return response.data;
  } catch (error: unknown) {
    const err = error as AxiosError;
    throw new Error(err.message);
  }
});

然后在组件中监听Thunk的执行状态,完成后导航:

import { useDispatch, useSelector } from 'react-redux';
import { useNavigate, useEffect } from 'react-router-dom';
import { loginAdminUser } from '../path/to/thunk';
import type { RootState, UserLoginProps } from '../types';

function LoginComponent() {
  const dispatch = useDispatch();
  const navigate = useNavigate();
  // 假设你的Login Slice中有status字段记录请求状态(fulfilled/rejected/pending)
  const loginStatus = useSelector((state: RootState) => state.login.status);

  useEffect(() => {
    // 登录请求成功完成时执行导航
    if (loginStatus === 'fulfilled') {
      navigate('/admin/home');
    }
  }, [loginStatus, navigate]);

  const handleLogin = (userData: UserLoginProps) => {
    dispatch(loginAdminUser(userData));
  };

  // 组件渲染逻辑...
}

方式三:用Redux Listener Middleware监听Action(推荐)

这种方式更符合Redux架构,把导航逻辑和组件、Thunk解耦,通过监听Thunk的成功Action触发导航:

  1. 创建并配置Listener Middleware:
import { configureStore, createListenerMiddleware, isAnyOf } from '@reduxjs/toolkit';
import { loginAdminUser } from '../path/to/thunk';
import { createBrowserHistory } from 'history';
import { loginReducer } from '../slices/loginSlice';

// 创建history实例用于导航
export const history = createBrowserHistory();

const listenerMiddleware = createListenerMiddleware();

// 监听loginAdminUser的成功Action
listenerMiddleware.startListening({
  matcher: isAnyOf(loginAdminUser.fulfilled),
  effect: () => {
    history.push('/admin/home');
  },
});

export const store = configureStore({
  reducer: {
    login: loginReducer,
    // 其他reducers...
  },
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware().prepend(listenerMiddleware.middleware),
});
  1. 修改React Router的Router组件,使用自定义的history实例:
import { Router } from 'react-router-dom';
import { history } from './store';
import { Provider } from 'react-redux';
import { store } from './store';

function App() {
  return (
    <Provider store={store}>
      <Router history={history}>
        {/* 你的路由配置 */}
      </Router>
    </Provider>
  );
}
  1. 最后修改Thunk,移除导航代码(和方式二的Thunk代码一致即可)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 22:10:26