question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Async defaultOptions is only updated on initial mount, not on property update

See original GitHub issue

When using an AsyncSelect component with defaultOptions turned on, changing the value of loadOptions does not cause said default options to refresh in order to reflect what’s contained in the new data source.

Test case

https://codesandbox.io/s/admiring-chatterjee-h1fbp?file=/src/App.tsx

Steps to reproduce

  1. Open the dropdown; the starting default options are 1, 2, 3, 4 and 5
  2. Untick the checkbox saying “Toggle source”.
  3. Reopen the dropdown; the starting default options are still 1, 2, 3, 4 and 5
  4. In the code editor, replace const [checked, setChecked] = useState(true); by const [checked, setChecked] = useState(false);
  5. Redo steps 1-3, notice how the options now say 6, 7, 8, 9, and 0

Expected behavior

Since ticking and unticking the box changes what function is being passed to loadOptions, one would expect that defaultOptions would be reloaded in consequence. This has been raised in #1581 and possible workarounds have been submitted in #2915 and #3639, but I feel that those miss the main issue, which is that the value of loadOptions isn’t tracked for potential changes.

Additionnal information

Here is the (only) point where defaultOptions is currently automatically populated, on initial mount:

https://github.com/JedWatson/react-select/blob/fd54f55e4d57fc9a63451a24eb963388a20fa0f0/packages/react-select/src/Async.js#L80-L91

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:10
  • Comments:5

github_iconTop GitHub Comments

1reaction
ebonowcommented, Dec 19, 2020

@sm-Fifteen I believe this is not a bug.

To start with, using the prefix default in the prop name is consistent with every other prop with the same prefix. It is only loaded on mount and has no bearing on later prop changes.

The defaultOptions are defined as:

The default set of options to show before the user starts searching. When set to true, the results for loadOptions(‘’) will be autoloaded.

I would say that this use-case of changing the loadOptions call is a bit nefarious as my understanding would be that autoloaded should mean that onMount it makes a one-time initial call with empty input. I don’t believe that defaultOptions should be responsible for knowing about changes made to the loadOptions prop which is what’s being done here.

One consequence of this is that you are now enforcing the user to provide useCallback on loadOptions to ensure that it’s not data fetching on every render (as the function signature could be different otherwise) and it’s likely you wouldn’t want to data fetch every time the user toggled the checkbox which this approach allows you the flexibility to do so otherwise.

What I would recommend if you wanted to pursue this kind of approach is to set the defaultOptions to state.

const [ defaultOptions, setDefaultOptions ] = useState(true);
const [ checked, setChecked ] = useState(true);

const loadOptions = (input) => {
   const data = checked ? data1 : data2;
   !input && data.then(options => setDefaultOptions(options));
   return data;
}

return (
      <AsyncSelect
        isMulti
        cacheOptions
        defaultOptions={defaultOptions}
        getOptionLabel={(el: string) => el}
        getOptionValue={(el: string) => el}
        loadOptions={loadOptions}
      />
);

If you have any further thoughts, questions, or concerns about this or the approach please feel free to reply and we can reopen this if necessary, but as described this seems to be functioning as designed.

0reactions
ebonowcommented, Feb 18, 2021

why would someone ever want to have defaultOptions be set to true and NOT have them reload when the loadOptions function changes? what would be a use case where that could ever be intuitive or beneficial to the developer?

defaultOptions fires onMount. Any additional changes in logic to the loadOptions functions are therefore done after the defaultOptions have already been fetched. In the provided example, the onLoad function is actually declared inline which means that it instantiates a new reference on every render. By your reasoning, it would call a data fetch on every new render.

This behavior seems far less intuitive or beneficial to the developer.

Consider instead that what we want to do is instead declare the side effects that would trigger a new fetch, and then use that effect to get the defaultOptions and pass that list to the defaultOptions instead of “true”. I hope this seems somewhat reasonable.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How trigger AsyncSelect to reload options in ReactJS
AsyncSelect loads the items when it gets mounted. But how can I trigger it programmatically (When I select the category from the first...
Read more >
class ApolloClient - Apollo GraphQL Docs
This is not the version of Apollo Client that you are using, but rather any ... Whether or not updates to the network...
Read more >
Async - React Select
defaultOptions. The defaultOptions prop determines "when" your remote request is initially fired. There are two valid values for this property. Providing an ...
Read more >
NFS in NetApp ONTAP. Best practice and implementation guide
Mounting multiple Qtrees in the same volume on the same NFS client . ... Beginning in ONTAP 9.1, a new way to present...
Read more >
19.2. Mounting a File System Red Hat Enterprise Linux 7
New Features and Enhancements in Red Hat Enterprise Linux 7 ... while a file system is mounted, the original content of the directory...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found