Async defaultOptions is only updated on initial mount, not on property update
See original GitHub issueWhen 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
- Open the dropdown; the starting default options are 1, 2, 3, 4 and 5
- Untick the checkbox saying “Toggle source”.
- Reopen the dropdown; the starting default options are still 1, 2, 3, 4 and 5
- In the code editor, replace
const [checked, setChecked] = useState(true);
byconst [checked, setChecked] = useState(false);
- 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:
Issue Analytics
- State:
- Created 3 years ago
- Reactions:10
- Comments:5
Top GitHub Comments
@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:
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.
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.
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.