使用Apollo的useQuery出现undefined报错的处理方案咨询
useQuery空值问题优化方案
你可以根据业务场景选择以下几种处理方式,不需要在每个使用useQuery的组件中单独重复写loading判断:
1. 利用内置状态前置校验
useQuery本身会返回loading、error字段,你可以在返回业务UI前先处理加载、异常状态,走到业务逻辑分支时data必然已加载完成,不需要额外做空值判断:
import {useQuery} from '@apollo/react-hooks'; import resolvers from '../../resolvers'; const DashboardComponent = () => { const {data, loading, error} = useQuery(resolvers.ReturnAllMovies); // 前置处理状态 if (loading) return <Loading />; if (error) return <ErrorTip content={error.message} />; // 此处data必然存在,无需可选链 const movies = data.movies; return ( <React.Fragment> <DashboardMovieOverviewMenu /> { movies.length > 0 && <MovieOverview /> } </React.Fragment> ); }; export default DashboardComponent;
2. 封装通用逻辑复用
如果项目中大量组件用到useQuery,可以将加载、异常的通用处理逻辑封装成自定义Hook或者高阶组件,一次封装多处调用:
自定义Hook示例:
// 全局封装 const useSafeQuery = (query, options) => { const res = useQuery(query, options); if (res.loading) return { ...res, data: options?.defaultData ?? {} }; if (res.error) throw res.error; return res; } // 组件内使用 const { data } = useSafeQuery(resolvers.ReturnAllMovies, { defaultData: { movies: [] } }); const movies = data.movies;
你也可以直接开启Apollo的Suspense模式,配合React的Suspense组件统一处理全局加载态,组件内部完全不需要感知loading状态。
3. 配置初始值省略校验
对于列表类简单查询场景,可以直接给useQuery配置initialData参数,初始化时就给data填充默认结构,自然不会出现undefined问题:
const { data } = useQuery(resolvers.ReturnAllMovies, { initialData: { movies: [] } }); const movies = data.movies;
内容的提问来源于stack exchange,提问作者Peter Boomsma
相关产品推荐
相关产品推荐

