SILENT
SILENT

Reputation: 4268

Debounce react-select graphql query

I'm trying to debounce graphql queries sent by my react-select component. I'm using wonka instead of rxjs but there's no tag for wonka.

const GraphqlQueryAsync = (query, outputFn) => (value) => {
  console.log({ value });
  return pipe(
    fromValue(value),
    // debounce(() => 5000),
    mergeMap((input) => client.executeQuery(createRequest(query, { input }))),
    map(outputFn),
    take(1),
    toPromise,
  );
};

React-select has a loadOptions function that calls my graphql query.

             <AsyncSelect
              defaultValue={value}
              styles={selectStyles(error)}
              placeholder={title}
              onChange={onChangeSelect(onChange, name, lefts)}
              defaultOptions
              loadOptions={GraphqlQueryAsync(query, outputFn)}
            />

My function works. However with debounce, it waits 5secs and still sends every value change. (ie if I type "rent", it would search for "r", "re", "ren", and "rent"). I believe this occurs because react-select repeatedly calls loadOptions function, creating multiple Graphql Queries. Is there anyway to allow loadOptions to continue passing the new values to the GraphqlQueryAsync function with debounce (ie send only "rent" search term)?

Upvotes: 1

Views: 2500

Answers (2)

SILENT
SILENT

Reputation: 4268

I was able to resolve using the callback feature of loadOptions.

let _GraphqlQueryDebounce;
const GraphqlQueryAsync = (query, outputFn) => (value, callback) => {
  console.log({ value });
  if(_GraphqlQueryDebounce) clearTimeout(_GraphqlQueryDebounce);
  _GraphqlQueryDebounce = setTimeout(async () => callback(
    await pipe(
      fromValue(value),
      mergeMap((input) => client.executeQuery(createRequest(query, { input }))),
      map(outputFn),
      take(1),
      toPromise,
    )
  ), 5000);
};

Upvotes: 1

Ali Mousavi
Ali Mousavi

Reputation: 915

Here's how you can debounce the function with a delay of 1000 ms:

let timerId = null

const loadOptionsDebounced = (query, outputFn) => {
    clearTimeout(timerId)
    timerId = setTimeout(() => {
        GraphqlQueryAsync(query, outputFn)
    }, 1000)
}

And in your select component:

<AsyncSelect
    loadOptions={loadOptionsDebounced(query, outputFn)}
</AsyncSelect>

Upvotes: 2

Related Questions