0

I am using react-select with async create table and implemented this to Netsuite custom page. The problem is that I want to load the getAsyncOptions function to trigger only when the user stops typing. At the moment these line of codes make the input field so slow as the function is getting triggered everytime a letter is added to the input. I also cant insert the fetched data to the state because it will be populated with a thousand records.

Email.tsx

getAsyncOptions(inputValue) {
return new Promise((resolve) => {
  var typingTimer; //timer identifier
  var doneTypingInterval = 1000; //time in ms (1 second)

  if (inputValue.length <= 3) {
    return resolve([]);
  }
  clearTimeout(typingTimer);
  if (inputValue) {
    return (typingTimer = setTimeout(function () {
      var t0 = performance.now();
      emailSearch(inputValue).then((data) => {
        const returnData = [];
        data.forEach((contact) => {
          returnData.push({
            label: contact.email + " - (" + contact.company + ")",
            value: contact.email,
          });
        });

        resolve(returnData);
        console.log(
          "Call to email search function took " +
            (t1 - t0) +
            " milliseconds."
        );
      });
      var t1 = performance.now();
    }, doneTypingInterval));
  }
});

As you see on the above code the it is only delaying the code to trigger. And another problem arises when the user stopped typing for 1 second and continue to type again, it is just delaying the function, and being triggered every 1 second. Here's the rest of the code for your reference.

RenderOpenMode.tsx

<AsyncCreatableSelect
     value={props.state.toEmailCollection}
     onChange={props.setToEmail}
     loadOptions={props.debouncedLoadQuery}
     styles={props.customSelectStylesEmail}
     components={{
       DropdownIndicator: () => null,
       IndicatorSeparator: () => null,
     }}
     isMulti={true}
     isSearchable={true}
     isValidNewOption={props.isValidNewOption}
     placeholder=""
     />

The Functions

this.setToEmail = (toEmailCollection) =>
  this.setState({ toEmailCollection: toEmailCollection });

this.setToCc = (toCcCollection) =>
  this.setState({ toCcCollection: toCcCollection });

const loadOptions = (inputValue) => this.getAsyncOptions(inputValue));
this.debouncedLoadQuery = debounce(loadOptions, 2000, {
  leading: true,
});

Been facing this roadblock for a while and any idea or help would be very much appreciated! Thank you so much and God bless!

Edit: Added some code. The onChange only updates some state, the problem is the loadOptions as it is the one that is triggering the getAsyncOptions.

Chadric Gotis
  • 117
  • 1
  • 13
  • What you're after is called a "debounce" function. Debouncing is when you delay execution of a function until it hasn't been called for some specific amount of time. https://stackoverflow.com/questions/15927371/what-does-debounce-do – Alex Wayne May 04 '21 at 23:48
  • I've added the debounce and seems that it is just delaying the loading of the fetched data. But while the data is being fetched the UI is being unresponsive. Thanks for the comment though! – Chadric Gotis May 04 '21 at 23:51
  • 1
    I initially marked this as a duplicate but then saw you were already trying to debounce *something*. "Trigger function when the user stops typing" basically translates to debounce the `onChange` handler, or whatever the `onChange` handler is updating. Can you provide a more comprehensive code example so we can trace the events from `onChange` to `emailSearch`? Does this [answer](https://stackoverflow.com/a/66394949/8690857) help? – Drew Reese May 04 '21 at 23:59
  • Updated the question. Thank you for response! – Chadric Gotis May 05 '21 at 00:10

1 Answers1

0

I've fixed the issue, it seems that the problem is on the debounce. I am using debounce-promise and the problem is that I've used leading=true option and that makes the UI unresponsive on change.

From this code:

this.debouncedLoadQuery = debounce(loadOptions, 2000, {
  leading: true,
});

To this code:

this.debouncedLoadQuery = debounce(loadOptions, 2000);
Chadric Gotis
  • 117
  • 1
  • 13