如何在调用 Apollo Graphql Query 之前等待服务器响应?
Posted
技术标签:
【中文标题】如何在调用 Apollo Graphql Query 之前等待服务器响应?【英文标题】:How to wait for server response before calling Apollo Graph QL Query? 【发布时间】:2020-12-02 19:16:08 【问题描述】:我在从我的 useEffect 挂钩接收数据后尝试调用 Graph QL 查询。我需要响应中的数据才能在查询中使用。然而,钩子不能有条件地调用。但是,如果我取消条件,loadedAnime 将是未定义的。如何绕过这种限制?
import React, useEffect, useState from "react";
import useParams from "react-router-dom";
import AnimeBanner from "../components/AnimeBanner";
import useHttpClient from "../Hooks/http-hook";
import GetAnimeData from "../GraphQLFunctions";
import useQuery from "@apollo/react-hooks";
import gql from "graphql-tag";
const GET_ANIME_INFO = gql`
query GetAnimeInfo($name: String!)
Media(search: $name)
title
romaji
english
native
userPreferred
episodes
id
bannerImage
`;
const Anime = (props) =>
//Logic for getting anime data from mongoDB (episodes, name, cover image)
const isLoading, error, sendRequest = useHttpClient();
const [loadedAnime, setloadedAnime] = useState();
const URLTitle = useParams().URLTitle;
useEffect(() =>
const fetchAnime = async () =>
try
const responseData = await sendRequest(
"http://localhost:5000/api/anime/" + URLTitle
);
setloadedAnime(responseData.animeData[0]);
catch (err)
console.log(err);
;
fetchAnime();
, [sendRequest, URLTitle]);
if (isLoading || error)
return null;
//Logic for getting anime data from anilist (Descriptions, tags, banner, trailer, etc.)
const apiData, apiLoading, apiError = useQuery(GET_ANIME_INFO,
variables:
name: loadedAnime.anime_name,
,
);
if (apiLoading || apiError)
return null;
return <AnimeBanner src=apiData.Media.bannerImage />;
;
export default Anime;
【问题讨论】:
【参考方案1】:简短回答:您可以签出 useLazyQuery 而不是 useQuery。
文档链接:https://www.apollographql.com/docs/react/data/queries/#executing-queries-manually
当 React 挂载并渲染一个调用 useQuery 钩子的组件时,Apollo Client 会自动执行指定的查询。但是,如果您想执行查询以响应不同的事件,例如用户单击按钮,该怎么办?
useLazyQuery 钩子非常适合执行查询以响应组件渲染以外的事件。这个钩子就像 useQuery 一样,有一个关键的例外:当 useLazyQuery 被调用时,它不会立即执行其关联的查询。相反,它会在结果元组中返回一个函数,您可以在准备好执行查询时调用该函数
import React, useState from 'react';
import useLazyQuery from '@apollo/client';
function DelayedQuery()
const [dog, setDog] = useState(null);
const [getDog, loading, data ] = useLazyQuery(GET_DOG_PHOTO);
if (loading) return <p>Loading ...</p>;
if (data && data.dog)
setDog(data.dog);
return (
<div>
dog && <img src=dog.displayImage />
<button onClick=() => getDog( variables: breed: 'bulldog' )>
Click me!
</button>
</div>
);
【讨论】:
【参考方案2】:您可以在 await
完成后调用查询,也可以在 api 调用后更新状态后在另一个 useEffect
中调用您的查询。一般来说,像这样,
const [state, setState] = useState()
useEffect(async () =>
const result = await get('/api/blah-blah-blah')
// run your query here now that the await has resolved
, [someDependency])
或
const [state, setState] = useState()
useEffect(async () =>
const result = await get('/api/blah-blah-blah')
setState(result)
, [someDependency])
useEffect(() =>
if(state.id)
// run the query
, [state.someProp])
【讨论】:
我无法使用这两种方法中的任何一种方法,使用这两种方法我都会收到错误“无法在回调 useeffect 中调用 React Hook “useQuery””。这可能是我自己的错误。但是我已经使用 Apollo 的 LazyQuery 在收到服务器响应后调用它来工作。不过谢谢!以上是关于如何在调用 Apollo Graphql Query 之前等待服务器响应?的主要内容,如果未能解决你的问题,请参考以下文章
Apollo/graphQL:如何将乐观 UI 用于嵌套反应组件的突变?
如何调试 nuxt-apollo 服务器端 graphql 请求
如何测试graphql apollo组件?如何在 compose() 中获得完整的覆盖?