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

使用React useEffect设置加载状态失败问题排查

问题原因

你的isLoading状态提前变为false,核心问题出在第二个useEffect的触发逻辑上:

  • 组件初始化时,problems的初始值是空数组[],error为undefined
  • 第一个useEffect调用TierService.getProblems后,不管API请求是否完成,第二个useEffect会因为problems和error的初始状态立即触发,直接执行setIsLoading(false),导致加载动画提前消失
解决方案

方案1:在API回调中手动控制加载状态

假设TierService.getProblems通过回调返回结果/错误,修改第一个useEffect,在请求完成(成功或失败)后再关闭加载状态:

const ProblemTable: React.FC<IProblemTableProps> = (props) => {
    const [problems, setProblems] = useState<IProblem[]>([]);
    const [isLoading, setIsLoading] = useState<boolean>(true);
    const [error, setError] = useState<Error>();

    useEffect(() => {
        setIsLoading(true);
        TierService.getProblems(
            props.tier,
            (data) => {
                setProblems(data);
                setIsLoading(false);
            },
            (err) => {
                setError(err);
                setIsLoading(false);
            }
        );
    }, [props.tier]);

    if (isLoading) {
        return <Loading message="Loading problems..." />;
    }

    if (error) {
        return <ErrorMessage title="Failed fetching problems" />;
    }

    return <>...</>;
};

方案2:改用Promise+async/await(推荐)

如果能修改TierService.getProblems让它返回Promise,代码会更简洁易维护:

// 先调整TierService.getProblems的实现,让它返回Promise
// 示例:
// class TierService {
//   static getProblems(tier: string): Promise<IProblem[]> {
//     return fetch(`/api/problems?tier=${tier}`).then(res => res.json());
//   }
// }

const ProblemTable: React.FC<IProblemTableProps> = (props) => {
    const [problems, setProblems] = useState<IProblem[]>([]);
    const [isLoading, setIsLoading] = useState<boolean>(true);
    const [error, setError] = useState<Error>();

    useEffect(() => {
        const fetchProblems = async () => {
            setIsLoading(true);
            try {
                const data = await TierService.getProblems(props.tier);
                setProblems(data);
            } catch (err) {
                setError(err as Error);
            } finally {
                // 不管成功失败,都关闭加载状态
                setIsLoading(false);
            }
        };

        fetchProblems();
    }, [props.tier]);

    if (isLoading) {
        return <Loading message="Loading problems..." />;
    }

    if (error) {
        return <ErrorMessage title="Failed fetching problems" />;
    }

    return <>...</>;
};

关键优化点

  • 移除原来的第二个useEffect,它无法区分“初始空数组”和“请求返回的空结果”,不能准确判断请求状态
  • 将props.tier加入依赖数组,确保tier变化时重新发起请求,符合React Hooks规范
  • 用finally块(或回调)确保加载状态一定会被关闭,避免出现加载动画一直显示的情况

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 04:01:45