为何TypeScript将接口返回的对象数据判定为布尔类型?
问题分析与修复方案
核心错误点
Context字段名不匹配
你定义的CategoryListContextType要求字段名为list,但Provider中传递的是{ data },TypeScript无法匹配类型,这是报错的直接原因。useGetApi缺少类型约束
useState()未指定泛型类型,TypeScript默认推断data为undefined,后续赋值后也无法正确识别数据结构;- Hook返回的数组没有类型标注,导致调用时无法获取正确的
data类型。
useEffect依赖逻辑错误
用JSON.stringify(data)作为依赖会触发无限循环:每次data更新都会生成新的字符串,导致useEffect重复调用handleFetch,不断发起接口请求。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
相关产品推荐
相关产品推荐

