如何在调用 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 突变

如何测试graphql apollo组件?如何在 compose() 中获得完整的覆盖?

更新 apollo 缓存而不调用 graphql 服务器(apollo v3.3)

如何连续进行 graphql 调用?反应阿波罗