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

React中useEffect内嵌套异步请求导致数据不渲染问题求助

问题分析与修复方案

核心问题

你的代码存在两个关键问题导致数据无法渲染:

1. 异步请求未正确等待,提前返回空数组

getMatchesWithStats 函数中,使用 map 结合 async/await 时,map 会立即返回一个包含Promise的数组,但函数不会等待这些Promise完成就直接返回了空的 matchesWithStats。此时所有请求还处于pending状态,返回的数组自然没有数据。

2. isLoading 状态管理错误,渲染条件逻辑颠倒

isLoading 初始值为 false,且在请求全程未更新状态,导致渲染条件 {isLoading && matchesRendered} 永远为假——即使后续 matches 有数据,也不会被渲染。


修复代码

1. 修正 getMatchesWithStats 函数

使用 Promise.all 等待所有异步请求完成,同时返回新对象避免修改原数据:

export const getMatches = async () => {
    const { data } = await axios.get(`https://***/matches`);
    const filteredLive = data.filter((item: TMatches) => item.live);
    console.log(filteredLive, 'filteredLive');
    return filteredLive;
}

export const getMatchesWithStats = async (matches: TMatches[]) => {
    // 用Promise.all等待所有请求完成,返回新的匹配项数组
    return Promise.all(matches.map(async (match) => {
        const { data } = await axios.get(`***/match?id=${match.id}`);
        // 返回新对象,避免直接修改原match产生副作用
        return { ...match, match: data };
    }));
}

2. 修正组件中的状态管理与渲染逻辑

正确控制 isLoading 状态,调整渲染条件,同时添加错误处理:

export const Matches = () => {
    const [matches, setMatches] = useState<TMatches[]>([]);
    const [isLoading, setLoading] = useState<boolean>(true); // 初始设为加载中

    useEffect(() => {
        const getUseMatch = async () => {
            try {
                const dataMatches = await getMatches();
                const dataMatchesWithStats = await getMatchesWithStats(dataMatches);
                setMatches(dataMatchesWithStats);
            } catch (error) {
                console.error('获取数据失败:', error);
                // 可添加错误提示逻辑
            } finally {
                setLoading(false); // 请求结束,关闭加载状态
            }
        }
        getUseMatch();
    }, []);

    const matchesRendered = matches.map((match) => {
        return (
            <>
                <StyledTeamName variant="h6">
                    <StyledIconLive>
                        <img src="/live.png" width="32" />
                    </StyledIconLive>
                    &nbsp;
                    {match.team1.name} - {match.team2.name}
                </StyledTeamName>
                <StyledTeamNameSubTitle>{match.event.name}</StyledTeamNameSubTitle>
            </>
        );
    });

    return (
        <>
            {/* 加载时显示提示,加载完成后显示数据 */}
            {isLoading ? <div>加载中...</div> : matchesRendered}
        </>
    );
}

额外说明

  • 避免副作用:直接修改原 match 对象可能导致意外的状态变化,返回新对象是更安全的做法。
  • 错误处理:添加 try/catch 可以捕获请求失败的情况,避免组件崩溃,同时可根据需求添加用户友好的错误提示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 14:05:18