React开发可复用API数据获取组件遇到的问题求解
解决方案
问题根源
- 初始输出undefined:接口请求是异步操作,组件第一次渲染时请求尚未返回,自定义Hook返回的state初始值为undefined,请求完成后调用setTeams触发重渲染才会返回真实数据,属于正常的异步渲染逻辑。
- TypeScript报错
Object is possibly 'undefined':你定义的teamsstate类型为Teams[] | undefined,未判空直接调用map方法时,TS会检测到潜在的调用undefined方法的风险,因此抛出类型错误。 - 额外隐藏问题:你在App组件中写的map回调使用了大括号但没有return语句,就算数据正常也无法渲染出列表项。
修复后的代码
1. 自定义Hook useGetTeamsByLeague.ts 优化
import axios from 'axios'; import { useEffect, useState } from 'react'; interface Teams { id: number; name: string; league: string; created_at: string; updated_at: string; } const useGetTeamsByLeague = (league: string) => { // 初始值设为空数组,类型固定为Teams[],不存在undefined情况 const [teams, setTeams] = useState<Teams[]>([]); // 新增loading状态,用于渲染加载态 const [loading, setLoading] = useState<boolean>(true); // 新增error状态,用于渲染错误提示 const [error, setError] = useState<string | null>(null); useEffect(() => { // 新增请求取消逻辑,避免内存泄漏 const controller = new AbortController(); setLoading(true); setError(null); axios .get(`http://awaydays-api.cb/api/teams/${league}`, { signal: controller.signal }) .then((response) => { setTeams(response.data); }) .catch((err) => { // 忽略请求取消的报错 if (!axios.isCancel(err)) { console.log(err); setError('队伍数据请求失败'); } }) .finally(() => { if (!controller.signal.aborted) { setLoading(false); } }); // 组件卸载时取消未完成的请求 return () => controller.abort(); }, [league]); // 导出三个状态,方便组件按需使用 return { teams, loading, error }; }; export default useGetTeamsByLeague;
2. App组件调用修改
import useGetTeamsByLeague from './Hooks/useGetTeamsByLeague'; import './Reset.scss'; function App() { // 解构获取三个状态 const { teams, loading, error } = useGetTeamsByLeague('Championship'); console.log(teams); if (loading) return <div>加载中...</div>; if (error) return <div>{error}</div>; return ( <div className='App'> <Header> {/* 箭头函数去掉大括号隐式返回,或者加return语句,同时添加key属性避免React警告 */} {teams.map(team => ( <li key={team.id}>{team.name}</li> ))} </Header> </div> ); } export default App;
修复效果说明
- TS报错直接消失:
teams的类型固定为Teams[],永远不会是undefined,无需额外判空即可调用数组方法。 - 异步逻辑更完善:新增的loading和error状态可以覆盖请求全流程的用户交互,不会出现初始空白或者报错崩溃的情况。
- 避免内存泄漏:新增的请求取消逻辑解决了组件卸载后请求返回还调用setState的潜在问题。
内容的提问来源于stack exchange,提问作者CIB
相关产品推荐
相关产品推荐

