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

React Typescript+Redux调用API更新状态时报proxy已撤销错误如何解决

问题原因

核心错误是在Redux Toolkit的reducer函数中编写了异步逻辑:

  • RTK的reducer底层用Immer库生成可修改的state代理对象,reducer同步执行完成后这个代理会立即被撤销回收
  • 你把fetchInitData异步请求写在了initData的reducer回调里,请求返回后执行then回调修改state的时候,代理已经被销毁,所以触发proxy revoked报错
修复方案

步骤1:调整questionReducers.ts,用createAsyncThunk封装异步逻辑

reducer必须是纯同步函数,所有异步请求都要放到RTK官方提供的thunk中间件中处理,修正后代码如下:

import {createAction, createReducer, createAsyncThunk} from '@reduxjs/toolkit';
import {fetchInitData} from './questionAPI';
import {AnswerInterface} from "../types/AnswerInterface";
import {Questions} from "../types/Questions";
import {RootState} from "./store";

interface QuestionsState {
    data: Questions,
    status: 'loading' | 'loaded' | 'error'
}

const initialState = {
    data: {
        question: {
            text: '',
            imageURL: ''
        },
        answers: [],
    },
    status: 'loading',
} as QuestionsState

export const appState = (state: RootState) => state;
export const addAnswer = createAction<AnswerInterface>('question/addAnswer')
// 封装异步请求thunk
export const fetchInitDataThunk = createAsyncThunk('app/fetchInitData', async () => {
    return await fetchInitData();
})

export const questionReducer = createReducer(initialState, (builder) => {
    builder
        // 匹配异步请求三个状态
        .addCase(fetchInitDataThunk.pending, (state) => {
            state.status = 'loading';
        })
        .addCase(fetchInitDataThunk.fulfilled, (state, action) => {
            state.data = action.payload;
            state.status = 'loaded';
        })
        .addCase(fetchInitDataThunk.rejected, (state) => {
            state.status = 'error';
        })
        .addCase(addAnswer, (state, action) => {
            state.data.answers.push(action.payload);
            localStorage.setItem('data', JSON.stringify(state.data));
        })
})

步骤2:修正App.tsx的错误

修复导入拼写错误、useEffect无依赖导致无限触发的问题:

import React, {useEffect} from 'react';
import styles from './App.module.css';
import { useAppSelector, useAppDispatch } from './app/hooks'
// 修正导入拼写错误,替换为thunk方法
import {fetchInitDataThunk, appState} from "./app/questionReducers";

const App:React.FC = () => {
    const state = useAppSelector(appState);
    const dispatch = useAppDispatch();
    // 加空依赖数组,仅组件挂载时触发一次请求
    useEffect(() => {
        dispatch(fetchInitDataThunk());
    }, [dispatch]);

    return (
        <div className={styles.App}>
            {state.status === 'loading' && <div>Loading...</div>}
            {state.status === 'loaded' && <div>Loaded...</div>}
            {state.status === 'error' && <div>加载失败,请稍后重试</div>}
        </div>
    );
}

export default App;

注意事项

  • 所有异步、副作用逻辑禁止直接写在reducer中,必须通过thunk、saga这类中间件实现
  • useEffect必须明确指定依赖数组,避免意外重复执行逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 07:06:02