web-dev-qa-db-fra.com

Est-il possible d'empêcher que les requêtes `useLazyQuery` soient récupérées lors du changement / du rendu d'état des composants?

Actuellement, j'ai un crochet useLazyQuery qui se déclenche en appuyant sur un bouton (partie d'un formulaire de recherche).

Le crochet se comporte normalement et ne se déclenche que lorsque le bouton est enfoncé. Cependant, une fois que je l'ai déclenché une fois, il est ensuite déclenché à chaque fois que le composant effectue un nouveau rendu (généralement en raison de changements d'état).

Donc, si je recherche une fois, puis édite les champs de recherche, les résultats apparaissent immédiatement et je n'ai pas besoin de cliquer à nouveau sur le bouton de recherche.

Pas l'interface utilisateur que je veux, et cela provoque une erreur si vous supprimez entièrement le texte de recherche (car il essaie de rechercher avec null comme variable), existe-t-il un moyen d'empêcher le useLazyQuery de en cours de récupération lors du re-rendu?

Cela peut être contourné en utilisant useQuery en fonction d'un état de "recherche" qui est activé lorsque je clique sur le bouton. Cependant, je préfère voir si je peux éviter d'ajouter de la complexité au composant.

const AddCardSidebar = props => {
  const [searching, toggleSearching] = useState(false);
  const [searchParams, setSearchParams] = useState({
    name: ''
  });
  const [searchResults, setSearchResults] = useState([]);
  const [selectedCard, setSelectedCard] = useState();

  const [searchCardsQuery, searchCardsQueryResponse] = useLazyQuery(SEARCH_CARDS, {
    variables: { searchParams },
    onCompleted() {
      setSearchResults(searchCardsQueryResponse.data.searchCards.cards);
    }
  });

  ...

  return (
    <div>
      <h1>AddCardSidebar</h1>
      <div>
        {searchResults.length !== 0 &&
          searchResults.map(result => {
            return (
              <img
                key={result.scryfall_id}
                src={result.image_uris.small}
                alt={result.name}
                onClick={() => setSelectedCard(result.scryfall_id)}
              />
            );
          })}
      </div>
      <form>

        ...

        <button type='button' onClick={() => searchCardsQuery()}>
          Search
        </button>
      </form>

      ...

    </div>
  );
};
8
user11754604

Le react-apollo la documentation ne mentionne pas si useLazyQuery doit continuer à déclencher la requête lorsque les variables changent, mais elles suggèrent d'utiliser le hook useApolloClient lorsque vous souhaitez déclencher manuellement une requête. Ils ont un exemple qui correspond à ce cas d'utilisation (cliquer sur un bouton déclenche la requête).

function DelayedQuery() {
  const [dog, setDog] = useState(null);
  const client = useApolloClient();

  return (
    <div>
      {dog && <img src={dog.displayImage} />}
      <button
        onClick={async () => {
          const { data } = await client.query({
            query: GET_DOG_PHOTO,
            variables: { breed: 'bulldog' },
          });
          setDog(data.dog);
        }}
      >
        Click me!
      </button>
    </div>
  );
}
8
Dylan Marshall

Vous n'avez pas besoin d'utiliser async avec le client apollo (vous pouvez, cela fonctionne). Mais si vous voulez utiliser useLazyQuery, il vous suffit de passer des variables sur onClick et non directement sur l'appel useLazyQuery.

Avec l'exemple ci-dessus, la solution serait:

function DelayedQuery() {
  const [dog, setDog] = useState(null);
  const [getDogPhoto] = useLazyQuery(GET_DOG_PHOTO, {
    onCompleted: data => setDog(data.dog)
  })

  return (
    <div>
      {dog && <img src={dog.displayImage} />}
      <button
        onClick={() => getDogPhoto({ variables: { breed: 'bulldog' }})}
      >
        Click me!
      </button>
    </div>
  );
}
1
Yann Pravo