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

如何让使用useReducer的React组件在axios调用完成后正确重渲染

问题根源

你遇到的问题本质是异步操作时序处理错误,所有尝试的方案都存在同一个问题:没有等待接口请求返回完整数据,就提前把未赋值的空Card对象提交到了状态里。

接口请求是异步执行的,你初始化空Card对象后直接返回/resolve,此时接口还没返回结果,拿到的永远是空对象。等后续接口请求完成修改Card对象时,React状态已经更新完成,不会自动响应这个对象的内部属性变化,所以会先显示空卡片,等到下一次状态更新触发重渲染时,之前修改过属性的Card才会正常显示,同时又会新增一个刚提交的空Card,形成你遇到的循环。

修复方案

1. 正确封装异步请求方法

用Promise.all等待两个接口都返回结果,组装好完整的Card对象后再返回,用async/await写法更易读:

// index.tsx
const getRandomPokemon = async (): Promise<Card> => {
  const randomInt = String(Math.floor(898 * Math.random()));
  // 并行请求两个接口,全部返回后再往下执行
  const [cardData, speciesData] = await Promise.all([
    PokemonDataService.getCard(randomInt),
    PokemonDataService.getSpecies(randomInt)
  ]);
  // 补全你之前省略的Card属性赋值逻辑,示例如下:
  const newCard: Card = {
    name: cardData.data.name,
    image: cardData.data.sprites.other["official-artwork"].front_default,
    // 其他从species接口取的属性
  };
  return newCard;
};

2. 调整点击事件逻辑,等待数据返回后再更新状态

const App = (props: AppProps) => {
  const [deck, dispatch] = useReducer(cardReducer, initialState);

  const addCard = async () => {
    try {
      // 等待接口返回完整数据后再dispatch更新状态
      const newCard = await getRandomPokemon();
      dispatch({
        type: ActionKind.Add,
        payload: newCard
      });
    } catch (err) {
      console.log(`获取宝可梦失败:\n ${err}`);
    }
  };

  return (
    <div>
      <Deck deck={deck} />
      <CatchButton onClick={addCard}>捕捉新宝可梦</CatchButton>
    </div>
  );
};

3. 可选优化项

简化reducer逻辑

不需要额外遍历克隆原有状态,直接展开数组即可,性能更好:

// cardReducer.tsx
export function cardReducer(state: Card[], action: Action): Card[] {
  switch (action.type) {
    case ActionKind.Add:
      return [...state, action.payload];
    default:
      return state;
  }
}

渲染层兼容处理

加可选链避免属性不存在时报错,也可以加加载状态提示:

// Deck.tsx
export const Deck = ({ deck }: DeckProps) => {
  return (
    <PokeDeck>
      {deck.map((card, index) => (
        <PokeCard key={index}>
          <img src={card?.image} alt={`${card?.name || '宝可梦'}的图片`} />
          <h2>{card?.name || '加载中...'}</h2>
        </PokeCard>
      ))}
    </PokeDeck>
  );
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 20:24:02