Vue监听prop变化调用useLazyQuery触发onServerPrefetch报错如何解决?
错误根因
这个报错的核心原因是useLazyQuery属于Vue组合式API封装的Apollo钩子,必须在setup函数的同步执行阶段直接调用,不能嵌套在异步函数、watch回调等非setup同步上下文中执行,否则会丢失组件实例关联,导致生命周期钩子注入失败。
另外你对useLazyQuery的用法也有问题:它本身不是异步方法,不需要await,调用后会返回一个手动触发查询的load方法,以及你需要的响应式状态result、error、loading。
修正方案
方案1:使用useLazyQuery手动触发查询
<script lang="ts"> import { ref, defineComponent, watch } from "vue"; import gql from "graphql-tag"; import { useLazyQuery, useResult } from "@vue/apollo-composable"; export default defineComponent({ props: { message: [String], }, setup(props) { const pageNumber = ref<number>(1); // 直接在setup顶层同步调用useLazyQuery const { load, result, error, loading } = useLazyQuery( gql` query getCharacters($page: Int!, $name: String!) { characters(page: $page, filter: { name: $name }) { info { count pages } results { id name image gender species episode { episode } } } location(id: 1) { id } episodesByIds(ids: [1, 2]) { id } } `, // variables设为响应式函数,每次触发查询都会自动取最新值 () => ({ page: pageNumber.value, name: props.message, }) ); // 直接用useResult解析响应数据,本身是响应式的 const characters = useResult(result, [], (res) => res.characters.results); // 监听prop变化,调用load手动触发查询 watch(() => props.message, () => { if (props.message) load(); }, { immediate: true }); // immediate设为true则组件初始化就触发第一次查询 // 把需要的状态返回给模板使用 return { characters, loading, error, pageNumber }; }, }); </script>
方案2:使用useQuery自动触发查询(更推荐)
如果不需要手动控制查询触发时机,直接用useQuery即可,它会自动监听响应式variables的变化自动重查,不需要额外写watch:
const { result, error, loading } = useQuery( gql`/* 同上的查询语句 */`, () => ({ page: pageNumber.value, name: props.message, }), { // 配置查询触发条件,比如message为空时不查询 enabled: () => !!props.message } ) const characters = useResult(result, [], (res) => res.characters.results);
内容的提问来源于stack exchange,提问作者Krzysztof
相关产品推荐
相关产品推荐

