How can I use debounce to avoid triggering the graphQL query on every keystroke in react?

How can I use debounce to avoid triggering the graphQL query on every keystroke in react?


0

I was given a new task and I have to debounce the input value to prevent a backend request on each keystroke and on the other hand CollectionsAutocomplete should have an internal useState with an input value, that is linked to the generalQuery variable.
Right now I was able to add the internal useState but I don’t know how to apply the debounce.
The CollectionsAutocomplete is a component that is located in our library and I use it in a different project.
Here is the CollectionsAutocomplete in the library:

type CollectionsAutocompleteProps = GenericFetchAutocompletePropsWrapperType<StyleCollection>
  & {
    targetBrandNumber: string;
    queryVariables?: Exact<{
      brandNumber: string;
      generalQuery?: InputMaybe<string> | undefined;
      pagination: PaginationInput;
    }> | undefined;
    onInputChange?: (inputValue: string) => void;
  };

export const CollectionsAutocomplete = (props: CollectionsAutocompleteProps): ReactElement => {
  const { queryVariables, targetBrandNumber, value, handleOnBlur, handleOnChange, handleOnFocus, limitTags, onInputChange } = props;
  const [inputValue, setInputValue] = useState<string>('');

  return (
    <GenericFetchAutocomplete<
      StyleCollection,
      GetAllCollectionsQuery,
      GetAllCollectionsQueryVariables,
      true>
      limitTags={limitTags}
      value={value}
      dataMapper={(data): Array<StyleCollection> =>
        data.collections?.edges?.map((edge) => edge?.node).filter(sortUtil.isDefined) ?? []}
      fetchQuery={GetAllCollectionsDocument}
      inputLabels={{
        plural: 'Collections',
        single: 'Collection',
      }}
      queryOptions={{
        fetchPolicy: 'network-only',
        context: { clientName: GraphClientNames['backend'] },
        variables: {
          generalQuery: queryVariables?.generalQuery ?? inputValue,
          brandNumber: targetBrandNumber,
          pagination: {
            first: 100,
            after: null,
          },
          ...queryVariables ?? {},
        },
      }}
      tagLabelFormatter={(option): string => `${option.collectionTerm} (${option.collectionName})`}
      textFieldProps={{
        ...props.textFieldProps,
        placeholder: value.length === 0 ? 'Select' : '',
        sx: {
          ['& ::placeholder']: {
            color: '',
          },
        },
      }}
      idKey='collectionNumber'
      optionLabelFormatter={(option): string => `${option.collectionTerm} (${option.collectionName})`}
      multiple
      onBlur={handleOnBlur}
      onChange={handleOnChange}
      onFocus={handleOnFocus}
      onInputChange={(event): void => {
        const newValue = (event.target as HTMLInputElement).value;
        setInputValue(newValue);
        onInputChange?.(newValue);
      }}
    />
  );
};

here is how I use the CollectionsAutocomplete in my project:

<CollectionsAutocomplete
                  value={collectionsValue}
                  textFieldProps={{ required: true }}
                  targetBrandNumber={selectedBrands[0]?.brandNumber}
                  queryVariables={{
                    pagination: {
                      first: 200,
                      after: null,
                    },
                  }}
                  handleOnChange={(e, v): void => {
                    if (v !== null) {
                      setCollectionsValue(v);
                    } else {
                      setCollectionsValue([]);
                    }
                  }}
                  onInputChange={(newValue: string): void => {
                    console.log('Input value changed:', newValue);
                  }}
                />

I’m a bit lost about how to apply the logic.


Load 7 more related questions


Show fewer related questions

0



Leave a Reply

Your email address will not be published. Required fields are marked *