【问题标题】:How to wait for server response before calling Apollo Graph QL Query?如何在调用 Apollo Graphql 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;

【问题讨论】:

    标签: javascript node.js reactjs apollo gql


    【解决方案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 在收到服务器响应后调用它来工作。不过谢谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-06
      • 2020-03-05
      • 2013-10-25
      • 1970-01-01
      • 2020-09-11
      • 2020-12-30
      相关资源
      最近更新 更多