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

使用@reduxjs/toolkit拉取大学列表时报proxy已撤销错误如何解决?

问题原因

你的核心错误是不应该在Redux Toolkit的reducer函数中执行异步请求逻辑:

  • RTK的reducer是纯函数,内部你拿到的state是Immer库生成的代理对象,reducer同步执行完成后这个代理就会被自动撤销回收
  • 你把接口请求放在reducer里,请求的then回调是异步执行的,等回调触发时state代理已经失效了,操作state.universities.push自然就会抛出"代理已撤销"的报错

另外还有两个隐藏问题:

  1. 你封装的axios请求URL里多了多余空格:search? country= 中?后面的空格会导致请求参数异常
  2. 组件里直接在函数顶层执行dispatch,会导致每次组件渲染都重复触发接口请求

修复方案

你需要使用RTK官方提供的createAsyncThunk来处理异步接口逻辑,调整代码如下:

1. 修正UniversityService的请求URL

import axios from "axios";

export default class UniversityService {
  getUniversitiesByCountry(countryName) {
    // 去掉?后的多余空格
    return axios
      .get("http://universities.hipolabs.com/search?country=" + countryName)
      .then((response) => response);
  }
}

2. 改造UniversitiesSlice,引入createAsyncThunk处理异步

import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import UniversityService from "../../service/UniversityService";

const universityService = new UniversityService();

// 定义异步请求thunk
export const fetchUniversitiesByCountry = createAsyncThunk(
  "universities/fetchByCountry",
  async (countryName) => {
    const response = await universityService.getUniversitiesByCountry(countryName);
    return response.data;
  }
);

export const universitiesSlice = createSlice({
  name: "universities",
  initialState: {
    universities: [],
  },
  reducers: {},
  // 监听异步请求的完成状态,更新state
  extraReducers: (builder) => {
    builder.addCase(fetchUniversitiesByCountry.fulfilled, (state, action) => {
      // 这里是同步执行,state代理还未失效,可以直接操作
      state.universities = action.payload;
      // 如果需要追加而非覆盖,就用state.universities.push(...action.payload)
    });
  },
});

export default universitiesSlice.reducer;

3. 修正ListPage的dispatch触发逻辑

import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { fetchUniversitiesByCountry } from './对应的slice路径';

export default function ListPage() {
  const dispatch = useDispatch();
  const universities = useSelector((state) => state.universities.universities);

  // 把dispatch放在useEffect里,只在组件挂载时触发一次
  useEffect(() => {
    dispatch(fetchUniversitiesByCountry("Turkey"));
  }, [dispatch]);

  console.log(universities);

  return (
    <div>
      <Table striped bordered hover>
        <thead>
          <tr>
            <th>#</th>
            <th>University Name</th>
            <th>Domain</th>
            <th>Web Page</th>
          </tr>
        </thead>
        <tbody>
          {universities.map((university, index) => (
            // 直接用map的第二个参数index作为key,性能优于indexOf
            <tr key={index}>
              <td>{index + 1}</td>
              <td>{university.name}</td>
              <td>{university.domains[0]}</td>
              <td>
                <a style={{ textDecoration: "none" }} href={university.web_pages[0]} target="_blank" rel="noreferrer">
                  {university.web_pages[0]}
                </a>
              </td>
            </tr>
          ))}
        </tbody>
      </Table>
    </div>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 13:39:03