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
相关产品推荐
相关产品推荐

