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

React fetch更新allCards后currentCard与showCard状态未更新问题

问题根因

  • fetchCards是异步函数,调用后不会立刻返回接口数据,你当前写的空依赖useEffect只会在组件首次挂载时执行一次,执行到allCards.length > 0的判断逻辑时,接口请求还未完成,allCards还是初始的空数组,所以currentCard和showCard的更新逻辑根本不会触发。
  • React状态更新是异步的,且空依赖的useEffect内部拿到的永远是组件首次挂载时的状态快照,就算后续allCards更新完成,这个useEffect也不会重新执行。

修复方案

方案1:拆分useEffect(适合allCards后续会更新的场景)

拆分两个useEffect,分别处理「组件挂载拉取卡片数据」和「卡片数据更新后刷新当前卡片」的逻辑:

const [showCard, setShowCard] = useState(false)
const [allCards, setallCards] = useState<CardProp[]>([]);
const [currentCard, setcurrentCard] = useState<CardProp>();

function getRandomCard() {
  return allCards[Math.floor(Math.random() * allCards.length)];
}
function updateCard() {
  setcurrentCard(getRandomCard());
}

const fetchCards = async () => {
  const cardRequest = await fetch("/api/card", {
    headers: {
      "Content-Type": "application/json",
      Authorization: token!,
    },
  });
  console.log(cardRequest);
  if (cardRequest.status === 200) {
    const cardJSON = await cardRequest.json();
    setallCards(cardJSON.cards);
  }
};

// 仅在组件挂载时触发,拉取卡片数据
useEffect(() => {
  fetchCards();
}, []);

// 监听allCards变化,数据加载完成后初始化当前卡片
useEffect(() => {
  if (allCards.length > 0) {
    setcurrentCard(getRandomCard());
    setShowCard(true);
  }
}, [allCards]);

方案2:直接在请求回调中设置(更简洁,适合allCards仅拉取一次的场景)

不需要新增额外的监听useEffect,拿到接口返回的卡片数据后直接设置所有状态即可:

const [showCard, setShowCard] = useState(false)
const [allCards, setallCards] = useState<CardProp[]>([]);
const [currentCard, setcurrentCard] = useState<CardProp>();

function updateCard() {
  setcurrentCard(allCards[Math.floor(Math.random() * allCards.length)]);
}

const fetchCards = async () => {
  const cardRequest = await fetch("/api/card", {
    headers: {
      "Content-Type": "application/json",
      Authorization: token!,
    },
  });
  console.log(cardRequest);
  if (cardRequest.status === 200) {
    const cardJSON = await cardRequest.json();
    const cards = cardJSON.cards;
    setallCards(cards);
    // 拿到数据后直接设置当前卡片和展示状态
    const randomCard = cards[Math.floor(Math.random() * cards.length)];
    setcurrentCard(randomCard);
    setShowCard(true);
  }
};

useEffect(() => {
  fetchCards();
}, []);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 11:00:00