Как дождаться ответа сервера перед вызовом запроса Apollo Graph QL?

#javascript #node.js #reactjs #apollo #gql

#javascript #node.js #reactjs #apollo #gql

Вопрос:

Я пытаюсь вызвать запрос Graph QL после получения данных из моего перехватчика useEffect. Мне нужны данные из ответа для использования в запросе. Однако хуки нельзя вызывать условно. Однако, если я уберу условие, 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 автоматически выполняет указанный запрос. Но что, если вы хотите выполнить запрос в ответ на другое событие, например, при нажатии пользователем кнопки?

Перехватчик 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 amp;amp; data.dog) {
    setDog(data.dog);
  }

  return (
    <div>
      {dog amp;amp; <img src={dog.displayImage} />}
      <button onClick={() => getDog({ variables: { breed: 'bulldog' } })}>
        Click me!
      </button>
    </div>
  );
}  

Ответ №2:

Вы можете либо вызвать запрос после await завершения, либо вы можете вызвать свой запрос в другом useEffect режиме, как только вы обновите состояние после вашего вызова api. В общем, что-то вроде этого,

 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])
  

Комментарии:

1. Я не смог сделать это ни одним из этих методов, с обоими из них я бы получил сообщение об ошибке «React Hook «useQuery»не может быть вызван внутри обратного вызова useeffect». Это могло быть из-за моей собственной ошибки. Но я заставил его работать, используя LazyQuery от Apollo, вызванный после получения ответа сервера. Хотя спасибо!