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

ReactJS Redux Toolkit根据ID取API数据:重复调用无法获取新ID数据

问题解决思路

1. 换ID不发起新请求的原因及解决

核心原因

要么是createAsyncThunk的默认缓存机制在参数相同时复用了旧请求结果,要么是组件没有在参数变化时重新触发dispatch。

解决步骤

步骤1:确保组件在参数变化时重新dispatch

检查组件中触发请求的逻辑,比如useEffect的依赖项是否包含scoreId和apiAddress,确保参数变化时重新调用thunk:

// 正确示例:依赖项包含所有变化的参数
useEffect(() => {
  dispatch(getScoreData({ apiAddress, scoreId }));
}, [apiAddress, scoreId, dispatch]);

步骤2:强制禁用thunk的缓存(可选)

如果确实需要每次调用都发起新请求,不管参数是否相同,可以给createAsyncThunk添加condition配置:

export const getScoreData = createAsyncThunk(
  'contentitem/scoredata',
  async (params) => {
    try {
      const res = await axios.get(`${params.apiAddress}api/v2/scores/${params.scoreId}`);
      return res.data;
    } catch (err) {
      console.error(err);
      throw err; // 必须抛出错误,让rejected状态正确触发
    }
  },
  {
    // 强制每次调用都发起新请求
    condition: () => true
  }
);

注意:原代码中then的错误处理会吞掉错误,导致rejected状态无法触发,建议改成try/catch并抛出错误。

2. 复用存储区域存同结构不同类型数据

当前的state.data是单个对象,每次请求会覆盖旧数据,需要改成键值对结构,用唯一标识(比如apiAddress+scoreId的组合)作为key,存储不同请求的结果:

修改initialState

const initialState = {
  // 键值对存储不同请求的数据,key为唯一标识
  items: {},
  loading: false,
  complete: false
};

修改slice的extraReducers

改用RTK推荐的builder语法,根据请求参数生成唯一key,将数据存入对应位置:

export const scoreSlice = createSlice({
  name: 'contentitem',
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(getScoreData.pending, (state, { meta }) => {
        state.loading = true;
        state.complete = false;
        // 生成唯一key
        const key = `${meta.arg.apiAddress}-${meta.arg.scoreId}`;
        // 初始化该条目的加载状态
        state.items[key] = { ...state.items[key], loading: true };
      })
      .addCase(getScoreData.fulfilled, (state, { payload, meta }) => {
        state.loading = false;
        state.complete = true;
        const key = `${meta.arg.apiAddress}-${meta.arg.scoreId}`;
        // 存储当前请求的数据
        state.items[key] = {
          data: payload,
          loading: false,
          complete: true
        };
      })
      .addCase(getScoreData.rejected, (state, { meta }) => {
        state.loading = false;
        state.complete = true;
        const key = `${meta.arg.apiAddress}-${meta.arg.scoreId}`;
        // 标记请求失败
        state.items[key] = {
          ...state.items[key],
          loading: false,
          complete: true,
          hasError: true
        };
      });
  }
});

组件中获取对应数据

使用时根据当前的apiAddress和scoreId生成key,从items中取出对应数据:

const { items } = useSelector(state => state.contentitem);
const currentKey = `${apiAddress}-${scoreId}`;
const currentData = items[currentKey]?.data;
const isLoading = items[currentKey]?.loading || false;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 03:15:52