Any way to abort loadable query?

I’m implementing a search combobox with async results. Here is some sample of code:

export const useTypeahead = () => {
  return useLoadableQuery(TypeaheadQuery, {
    fetchPolicy: 'network-only',
  });
};

// ....

const SearchTypeahead = () => {
  const [loadQuery, queryRef, refHandlers] = useTypeahead();
  const [query, setQuery] = useState(defaultValue || '');

  const debouncedLoad = useDebouncedCallback<typeof loadQuery>((vars) => {
    startTransition(() => {
      loadQuery(vars);
    });
  }, 200);

  const onQueryChange = (query: string) => {
    if (query.length === 0) {
      refHandlers.reset();
    } else {
      debouncedLoad({ query });
    }

    setQuery(query);
  };

  // .....
}

As you can see I use debounce and also reset the query as soon as user clears search input. It works fine but I experience the next race condition:

  1. User types some text
  2. We send request
  3. at that moment user immediately clears the input
  4. we reset queryRef
  5. request from step 2 ends and overwrites cache which leads to showing outdated data for cleared text query

So I have two questions:

  1. Shouldn’t reset also abort all ongoing requests?
  2. Is there a way to pass abort signal to loadQuery function? As I can see I can only pass it to the hook itself but this way not sure how am I supposed to pass the correct reference to signal

Thanks in advance for any tips :bowing_man:

Shouldn’t reset also abort all ongoing requests?

No, the reset function just resets the hooks internal state, but doesn’t influence requests. Your queryRef is still valid.

Is there a way to pass abort signal to loadQuery function? As I can see I can only pass it to the hook itself but this way not sure how am I supposed to pass the correct reference to signal

Unfortunatelt not at this point, but this is certainly something to consider. Thank you for bringing it up, I’ve pinged my colleague on it.

request from step 2 ends and overwrites cache which leads to showing outdated data for cleared text query

Generally, this seems worrysome to me. Do you have manual typePolicies in place that merge requests with different variables into the same cache entry?

oh, I found the problem…

I was resetting queryRef when query === '' but I forgot to cancel pending debounced function :man_facepalming: This way actual request was started after the reset

After canceling the debounce seems like the original issue is gone. Thank you for looking in

1 Like