Apollo Client组件重渲染时useQuery未触发执行问题咨询
问题原因
useQuery默认的fetchPolicy为cache-first(缓存优先),只要查询参数没有发生变化、缓存中存在对应数据,就不会主动发起新的网络请求。你通过rerender状态触发的组件重渲染没有改变useQuery的入参,因此不会触发重新查询。- 你在缓存配置中自定义了
Query.movies字段的read方法,直接返回movieVar的值,这会导致所有对movies字段的读取都优先走你自定义的逻辑,接口返回的原始数据会被覆盖,即便发起请求也不会更新data的结果。 - 你的
movieVar类型配置错误:当前movieVar定义为单个IMovie对象,但接口返回的movies是数组,类型不匹配会导致后续逻辑异常。 - 自定义的
useEffect逻辑无效:你在useEffect中修改的是局部变量movies,组件重渲染后该变量会被重置为data?.movies,追加操作不会生效;同时useReactiveVar是Hook,不能直接放在依赖数组中调用,需要在组件顶层调用后将返回值放入依赖。
修复方案
你不需要手动写useEffect和触发重渲染的状态,Apollo会自动感知响应式变量的变化更新查询结果,按以下步骤修改即可:
步骤1:调整缓存配置
修改movies字段的read方法,合并接口返回的原有列表和响应式变量存储的新增电影,避免覆盖原始数据:
// cache.tsx import {InMemoryCache, ReactiveVar, makeVar} from '@apollo/client'; import {IMovie} from './movieseat'; export const movieVar: ReactiveVar<IMovie> = makeVar<IMovie>({id: 0, original_title: '', backdrop_path: '', poster_path: '', release_date: ''}); export const cache: InMemoryCache = new InMemoryCache({ typePolicies: { Query: { fields: { movies: { read(existingMovies: IMovie[] = []) { const newMovie = movieVar(); // 过滤空对象、避免重复添加 if (newMovie.id && !existingMovies.some(movie => movie.id === newMovie.id)) { return [...existingMovies, newMovie]; } return existingMovies; }, }, }, }, }, });
步骤2:简化MovieOverview组件
删除冗余的状态和副作用逻辑,直接使用useQuery返回的数据即可,Apollo会在movieVar更新时自动更新查询结果、触发组件重渲染:
// MovieOverview.tsx const MovieOverview = () => { const {loading, error, data} = useQuery(resolvers.queries.ReturnAllMovies); if (loading) return <p>loading</p>; if (error) return <p>Error! ${error.message}</p>; return ( <div> {data?.movies?.length || 0} </div> ); };
步骤3(可选):新增后同步服务端数据
如果你需要在添加电影后拉取服务端最新的全量列表,可以在useMutation中添加refetchQueries配置,指定新增完成后重新执行ReturnAllMovies查询:
// addMovie.tsx const [addMovieRes] = useMutation(resolvers.mutations.AddMovie, { // mutation执行成功后自动重新拉取电影列表 refetchQueries: [resolvers.queries.ReturnAllMovies], }); addMovieRes({variables: { original_title: movie.original_title, tmdb_id: movie.id, poster_path: movie.poster_path, }}); movieVar(movie);
内容的提问来源于stack exchange,提问作者Peter Boomsma
相关产品推荐
相关产品推荐

