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

使用createAsyncThunk实现异步Action成功后在组件内重定向的正确方法

实现方案

核心逻辑完全收在组件内部,不耦合路由依赖到异步thunk里,利用createAsyncThunk dispatch后返回的action自带状态标记,精准判断请求结果,只有成功时才触发跳转。

具体改动点

  • 从react-router-dom引入useNavigate hook,在组件内拿到路由跳转能力
  • 在提交回调中等待dispatch异步thunk的结果,通过action的状态类型判断是否为成功请求
  • 仅匹配到成功状态时,执行navigate('/tasks')跳转
  • 请求出错时,流程自然走到判断分支外,不触发任何跳转逻辑

完整可运行的组件代码

import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
// 引入路由导航能力
import { useNavigate } from 'react-router-dom';

import { RootStateType, AppDispatch} from '../../store';
import { changeTask } from '../../reducers/todo'; 
import { addTodo } from '../../async-thunks/todo';
import Form from '../../components/form';
import Button from '../../components/button';
import Input from '../../components/input';

const NewTask: React.FC = () => {
  const dispatch = useDispatch<AppDispatch>();
  // 初始化导航函数
  const navigate = useNavigate();
  const newTask = useSelector((state: RootStateType) => state.todo.newTask);

  const onTaskAdd = async (event: React.FormEvent<HTMLFormElement>) => {
    // 阻止表单默认提交导致的页面刷新
    event.preventDefault();
    const dispatchedAction = await dispatch(addTodo(newTask));
    // 仅匹配thunk的成功action时才跳转
    if (dispatchedAction.type === 'tasks/addTask/fulfilled') {
      navigate('/tasks');
    }
  };

  const onTaskNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    event.stopPropagation();
    dispatch(changeTask(event.target.value));
  };

  return (
    <Form onSubmit={onTaskAdd}>
      <Input type="text" value={newTask} onChange={onTaskNameChange}></Input>
      <Button type="submit">Submit</Button>
    </Form>
  );
};

export default React.memo(NewTask);

补充说明

  • 这种写法不需要额外写全局错误捕获,只要请求失败(不管是网络异常、接口报错、thunk内部抛错),都会触发tasks/addTask/rejected类型的action,永远不会进入跳转判断分支,完全匹配需求
  • 也可以用unwrap()写法实现等价逻辑,但需要搭配try/catch块捕获失败抛出的异常,否则会出现未捕获的Promise报错,相比之下直接判断action类型的写法侵入性更低:
    // 等价写法示例
    try {
      await dispatch(addTodo(newTask)).unwrap();
      navigate('/tasks');
    } catch (err) {
      // 失败分支,不跳转
    }
    
  • 整个跳转逻辑全程在组件内部完成,没有把路由相关的依赖传入异步thunk,保证了thunk的可复用性,没有破坏原有代码的结构分层。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.24 01:36:01