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

为何TypeScript将接口返回的对象数据判定为布尔类型?

问题分析与修复方案

核心错误点

  1. Context字段名不匹配
    你定义的CategoryListContextType要求字段名为list,但Provider中传递的是{ data },TypeScript无法匹配类型,这是报错的直接原因。

  2. useGetApi缺少类型约束

  • useState()未指定泛型类型,TypeScript默认推断data为undefined,后续赋值后也无法正确识别数据结构;
  • Hook返回的数组没有类型标注,导致调用时无法获取正确的data类型。
  1. useEffect依赖逻辑错误
    用JSON.stringify(data)作为依赖会触发无限循环:每次data更新都会生成新的字符串,导致useEffect重复调用handleFetch,不断发起接口请求。

  2. loading状态处理错误
    请求失败时应该设置setLoading(false),否则错误状态下会一直处于加载中。


修复后的完整代码

1. 修复useGetApi Hook

import { useState, useEffect } from 'react';
import axios from 'axios';

// 添加泛型支持,适配不同接口返回类型
export const useGetApi = <T>(link: string) => {
    // 指定泛型,初始值为undefined
    const [data, setData] = useState<T | undefined>(undefined);
    const [loading, setLoading] = useState(true);

    const handleFetch = async () => {
        const cancelToken = axios.CancelToken.source();
        try {
            const response = await axios.get(link, { cancelToken: cancelToken.token });
            setLoading(false);
            setData(response.data.data as T); // 断言为指定类型
        } catch (err) {
            setLoading(false); // 错误时结束加载状态
            console.error('请求失败:', err);
        }
    };

    useEffect(() => {
        handleFetch();
        // 组件卸载时取消未完成的请求,避免内存泄漏
        return () => cancelToken.cancel('组件卸载,取消请求');
    }, [link]); // 仅依赖link,避免无限循环

    return [data, loading] as const; // 让TypeScript推断为元组类型
};

2. 修复Context相关代码

import { createContext, useContext, ReactNode, FC } from 'react';
import { useGetApi } from './useGetApi';

export type ChildrenProps = {
    children?: ReactNode;
};

export type CategoryListProps = {
    national: boolean;
    business: boolean;
    sports: boolean;
};

export type CategoryListContextType = {
    list: CategoryListProps | undefined; // 允许undefined,适配初始加载状态
};

const CategoryList = createContext<CategoryListContextType | null>(null);

export const useCategoryList = () => {
    const contextValue = useContext(CategoryList);
    if (!contextValue) {
        throw new Error("CategoryList context must be used inside CategoryList provider");
    }
    return contextValue;
};

export const CategoryListProvider: FC<ChildrenProps> = (props) => {
    // 传入CategoryListProps作为泛型,指定返回数据类型
    const [data, loading] = useGetApi<CategoryListProps>("/feeds/category");
    // 匹配Context定义的字段名list
    const value = { list: data };

    // 加载中时渲染占位符,避免子组件访问undefined属性报错
    if (loading) {
        return <div>加载中...</div>;
    }

    return <CategoryList.Provider value={value}>{props.children}</CategoryList.Provider>;
};

额外说明

  • 泛型化的useGetApi可复用在其他接口请求场景,只需传入对应的数据类型;
  • Provider中添加loading判断,能避免子组件在数据未就绪时出现属性访问错误;
  • 请求取消逻辑可以防止组件卸载后未完成的请求导致内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 02:45:33