Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: remove loading indicator when typing in select #18799

Merged
merged 10 commits into from
Mar 3, 2022

Conversation

ktmud
Copy link
Member

@ktmud ktmud commented Feb 17, 2022

SUMMARY

Remove the loading indicator in select option menus when users are typing and (some) options are already loaded. The loading indicator showing up as users type was added in #16531, while tackling the issue of the inaccurate "No data" message when data is still loading. But we shouldn't show "Loading..." when there are already filtered options available. Removing this unnecessary loading indicator makes the control feels faster.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

Before

The "Loading..." option shows up as soon as users type, even when all options are loaded:

before-select

After

No "Loading..." option when users start to type, but there is a loading indicator in the input and all filtered options will show up after actual loading is finished:

acceptable-select

When all options are loaded for a specific search string, there is no loading indicator at all and no excessive requests will be fired.

TESTING INSTRUCTIONS

  1. Run npm run storybook in superset-frontend
  2. Test it in the storybook: http://localhost:6006/?path=/story/select--async-select
    1. Try search for something in and not in the first page. E.g. "ale", "sandro"
    2. "No data" should not show up if there is a match in loaded options or the next page is still loading
    3. "Loading..." should not show up if there is already a matched option

ADDITIONAL INFORMATION

@codecov
Copy link

codecov bot commented Feb 22, 2022

Codecov Report

Merging #18799 (e4ae742) into master (bd63a1b) will decrease coverage by 0.00%.
The diff coverage is 84.21%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master   #18799      +/-   ##
==========================================
- Coverage   66.58%   66.58%   -0.01%     
==========================================
  Files        1641     1641              
  Lines       63533    63538       +5     
  Branches     6424     6428       +4     
==========================================
+ Hits        42303    42305       +2     
- Misses      19551    19553       +2     
- Partials     1679     1680       +1     
Flag Coverage Δ
javascript 51.38% <84.21%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
superset-frontend/src/components/Select/utils.ts 59.09% <66.66%> (+1.19%) ⬆️
superset-frontend/src/components/Select/Select.tsx 86.69% <85.71%> (-0.67%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update bd63a1b...e4ae742. Read the comment docs.

@michael-s-molina
Copy link
Member

@ktmud I found some problems while testing.

The loading indicator is different when we open the select vs when we search for something.

Screen.Recording.2022-02-23.at.1.44.25.PM.mov

The loading spinner is showing after searching and clicking outside the Select. When fetchOnlyOnSearch is true it never stops spinning.

Screen.Recording.2022-02-23.at.1.55.35.PM.mov

@ktmud
Copy link
Member Author

ktmud commented Feb 23, 2022

@michael-s-molina Thanks for testing! I've fixed both issues.

@michael-s-molina
Copy link
Member

@michael-s-molina Thanks for testing! I've fixed both issues.

@ktmud I just tested it again and the bugs are still happening. Did you forget to commit something?

I also noticed that you removed the debounce from handleOnSearch which is triggering this expensive calculation for every typed key.

Screen.Recording.2022-02-25.at.9.03.22.AM.mov

@ktmud
Copy link
Member Author

ktmud commented Feb 28, 2022

@michael-s-molina are you sure you pulled the latest changes? The bugs are fixed for me.

debounce is removed for handleOnSearch but the actual expensive operations are still debounced as in debouncedHandleSearch.

@michael-s-molina
Copy link
Member

debounce is removed for handleOnSearch but the actual expensive operations are still debounced as in debouncedHandleSearch.

This part is not debounced:

if (allowNewOptions && isSingleMode) {
    const newOption = searchValue &&
      !hasOption(searchValue, selectOptions) && {
        label: searchValue,
        value: searchValue,
        isNewOption: true,
      };
    const cleanSelectOptions = selectOptions.filter(
      opt => !opt.isNewOption,
    );
    const newOptions = newOption
      ? [newOption, ...cleanSelectOptions]
      : cleanSelectOptions;
    setSelectOptions(newOptions);
  }
  if (isAsync && !allValuesLoaded && loadingEnabled) {
    setIsLoading(search !== searchedValue);
  }

@ktmud
Copy link
Member Author

ktmud commented Feb 28, 2022

It's not really expensive. The goal of this whole PR is to make the select options update more responsively to user inputs, which is achieved by separating initial filtering and menu state updates with debounced async requests.

@michael-s-molina
Copy link
Member

@michael-s-molina are you sure you pulled the latest changes? The bugs are fixed for me.

Screen.Recording.2022-02-28.at.4.44.13.PM.mov

@michael-s-molina
Copy link
Member

It's not really expensive. The goal of this whole PR is to make the select options update more responsively to user inputs, which is achieved by separating initial filtering and menu state updates with debounced async requests.

You can see the loading indicator flicking while you type because it's updating the loading state for every key typed.

Screen.Recording.2022-02-28.at.4.55.19.PM.mov

@ktmud
Copy link
Member Author

ktmud commented Feb 28, 2022

@michael-s-molina I can reproduce the bug now. Looks like this might need a larger refactoring than I thought it needed. Thanks for testing!

@ktmud
Copy link
Member Author

ktmud commented Mar 1, 2022

@michael-s-molina This should be ready for re-review.

Copy link
Member

@michael-s-molina michael-s-molina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The allowNewOptions is not working as intended. If you add a new option and then search for it then it will disappear from the options.

Screen.Recording.2022-03-02.at.9.38.08.AM.mov

superset-frontend/src/components/Select/Select.tsx Outdated Show resolved Hide resolved
@ktmud
Copy link
Member Author

ktmud commented Mar 2, 2022

The allowNewOptions is not working as intended. If you add a new option and then search for it then it will disappear from the options.

This should have been fixed

@geido
Copy link
Member

geido commented Mar 2, 2022

/testenv up

@github-actions
Copy link
Contributor

github-actions bot commented Mar 2, 2022

@geido Ephemeral environment spinning up at http://34.217.29.213:8080. Credentials are admin/admin. Please allow several minutes for bootstrapping and startup.

Copy link
Member

@michael-s-molina michael-s-molina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't found any other problems while testing. Thank you so much @ktmud for improving the user experience of the component and for addressing all suggestions.

@geido was doing some tests with real data so I would kindly request to wait for his approval as well before merging the PR given the critical nature of the component.

Comment on lines +70 to +72
optionsArray.find(x =>
typeof x === 'object' ? x.value === value : x === value,
) !== undefined
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
optionsArray.find(x =>
typeof x === 'object' ? x.value === value : x === value,
) !== undefined
optionsArray.find(option =>
typeof option === 'object' ? option.value === value : option === value,
) !== undefined

Copy link
Member Author

@ktmud ktmud Mar 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general I prefer to use x in these one liners because sometimes you may want to rename the iterable variable as well.

@ktmud ktmud merged commit 5a8eb09 into apache:master Mar 3, 2022
@github-actions
Copy link
Contributor

github-actions bot commented Mar 3, 2022

Ephemeral environment shutdown and build artifacts deleted.

villebro pushed a commit that referenced this pull request Apr 3, 2022
@john-bodley john-bodley deleted the no-loading-when-typing branch June 8, 2022 05:29
@mistercrunch mistercrunch added 🍒 1.5.0 🍒 1.5.1 🍒 1.5.2 🍒 1.5.3 🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels 🚢 2.0.0 labels Mar 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels lts-v1 size/L 🍒 1.5.0 🍒 1.5.1 🍒 1.5.2 🍒 1.5.3 🚢 2.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants