如何在TypeScript中提取涉及本地state setState的组件Axios请求?
问题解决:将组件内请求函数迁移至service.ts并修复类型错误
问题背景
想把FavoriteList组件中的getFavList请求函数迁移到service.ts中,但因函数涉及组件的setAllData状态更新函数,迁移后出现类型不匹配错误:
Argument of type 'any[]' is not assignable to parameter of type 'SetStateAction<[]>'.
Type 'any[]' is not assignable to type '(prevState: []) => []'.
Type 'any[]' provides no match for the signature '(prevState: []): []'.
错误原因
service.ts中AxiosArg接口对setAllData的类型定义错误:使用了Dispatch<SetStateAction<[]>>,而组件中allData的类型是Data[],空数组类型[]与Data[]不兼容;- axios请求未指定返回数据类型,导致
res.data.charities被推断为any[],进一步加剧类型不匹配。
解决方案
方案1:修正类型定义(保留传setAllData的写法)
修改service.ts的类型定义,使其与组件状态类型一致,并为axios请求添加类型声明:
// 导入必要类型(需确保Data类型可被service.ts访问,比如从公共类型文件导入) import axios from 'axios'; import { Dispatch, SetStateAction } from 'react'; import { Data } from './types'; // 假设Data类型定义在types.ts中 interface AxiosArg { API: string; setAllData: Dispatch<SetStateAction<Data[]>>; // 修正为Data[]类型 } const getFavList = async ({ API, setAllData }: AxiosArg) => { try { // 为axios请求指定返回数据类型,确保charities是Data[] const res = await axios.get<{ charities: Data[] }>(`${API}/api/favCharityList`); setAllData([...res.data.charities]); } catch (err) { console.error(`Error: ${err}`); } }; export { getFavList };
组件代码保持现有调用方式即可,无需额外修改。
方案2:解耦service与组件状态(推荐实践)
让service只负责数据请求并返回数据,状态更新逻辑留在组件中,这样service更通用,不依赖React状态函数:
修改后的service.ts
import axios from 'axios'; import { Data } from './types'; export const getFavList = async (API: string): Promise<Data[]> => { try { const res = await axios.get<{ charities: Data[] }>(`${API}/api/favCharityList`); return [...res.data.charities]; } catch (err) { console.error(`Error: ${err}`); return []; // 出错时返回空数组,避免组件报错 } };
修改后的组件代码
export default function FavoriteList() { const [allData, setAllData] = useState<Data[]>([]); const [hasUpdated, setHasUpdated] = useState<boolean>(true); useEffect(() => { const fetchData = async () => { const data = await getFavList(API); setAllData(data); }; fetchData(); }, [hasUpdated]); return <></>; }
关键说明
- 确保
Data类型在service.ts和组件中都能访问,可将类型定义抽离到单独的types.ts文件中; - 避免混用
await和.then(),统一用try/catch处理异步错误,代码更清晰; - 方案2的解耦写法更符合单一职责原则,service专注数据请求,组件专注状态管理与渲染,更易维护。
内容的提问来源于stack exchange,提问作者Leung Cho-shing
相关产品推荐
相关产品推荐

