-
Notifications
You must be signed in to change notification settings - Fork 13.9k
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
fix: Select onChange is being fired without explicit selection #24698
fix: Select onChange is being fired without explicit selection #24698
Conversation
10730fb
to
ad25283
Compare
ad25283
to
9712800
Compare
const [onChangeCount, setOnChangeCount] = useState(0); | ||
const previousChangeCount = usePrevious(onChangeCount, 0); | ||
|
||
const fireOnChange = useCallback( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Simple counter used to fire the onChange
event.
fullSelectOptions.filter(opt => set.has(opt.value)), | ||
); | ||
if (isSingleMode) { | ||
// @ts-ignore |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The original typescript definition does not allow undefined
but I checked and the component allows it when using allowClear
.
: option.value, | ||
), | ||
); | ||
if (isSingleMode) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Single mode was previously using an empty array but it should be undefined
.
newValues = mapValues(array, labelInValue); | ||
newOptions = mapOptions(array); | ||
} | ||
onChange?.(newValues, newOptions); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No relevant changes to handleOnChange
apart from adding useCallback
.
onDeselect={handleOnDeselect} | ||
onDropdownVisibleChange={handleOnDropdownVisibleChange} | ||
onPopupScroll={undefined} | ||
onSearch={shouldShowSearch ? handleOnSearch : undefined} | ||
onSelect={handleOnSelect} | ||
onClear={handleClear} | ||
onChange={handleOnChange} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
onChange
is now manually fired when there's an actual change by the user.
label: opt.label, | ||
disabled: opt.disabled, | ||
...opt, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Options may contain custom fields and these should be present when mapping.
test('does not fire onChange when searching but no selection', async () => { | ||
const onChange = jest.fn(); | ||
render( | ||
<div role="main"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This div
is to simulate a click outside of the select.
Codecov Report
@@ Coverage Diff @@
## master #24698 +/- ##
==========================================
+ Coverage 58.35% 67.24% +8.88%
==========================================
Files 1901 1902 +1
Lines 73933 73996 +63
Branches 8183 8195 +12
==========================================
+ Hits 43146 49760 +6614
+ Misses 28666 22117 -6549
+ Partials 2121 2119 -2
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 342 files with indirect coverage changes 📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
@jinghua-qa @sadpandajoe Could you help us test the PR? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @michael-s-molina thanks for this. I see we are adding a bunch of logic to control how the onChange event is being triggered. Just trying to understand what's the benefit of doing this VS enforcing that the wrapper components use the onSelect / onDeselect handlers instead?
That's a great question. The difference is that the |
9712800
to
bd24802
Compare
Co-authored-by: JUST.in DO IT <justin.park@airbnb.com>
/testenv up |
@geido Ephemeral environment spinning up at http://35.92.133.95:8080. Credentials are |
@michael-s-molina I think it makes sense to make the I found a small issue. When clicking on the input when there is a search value, the search value disappears. I think we need to control the target of the click. FCC.New.Coder.Survey.2018.mp4Another weird aspect of the Select, that has nothing to do with this PR, but that I'd like to point out. When hitting Enter on a new search value, I am expecting that the value will be added to the options, like it happens when there is no other match and the value is new. However, when the search value matches with an already selected value that is focused, hitting Enter not only does not select the search value, but deselects the focused value, which is super confusing. FCC.New.Coder.Survey.2018.1.mp4 |
I exposed
This is a bug with Ant Design that was fixed on version 4.24.5 which is some leap from our current 4.10.3 version. Unfortunately, we may delay this fix until Ant Design is upgraded. |
What's happening is that when you select an option, it gets focused and that's why when you press Enter, it gets unselected. If you use the arrow keys after selecting an item, you can see that if you focus a different option and press Enter it will get selected. So it's not related to the search value matching a selected option. One way we could improve this would be to always auto focus the next option after the selected ones but I didn't find a way to programmatically change the focus. Screen.Recording.2023-07-21.at.11.27.51.mov |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for all the work on this!
Ephemeral environment shutdown and build artifacts deleted. |
Co-authored-by: JUST.in DO IT <justin.park@airbnb.com> (cherry picked from commit 6089b5f)
…e#24698) Co-authored-by: JUST.in DO IT <justin.park@airbnb.com>
SUMMARY
This PR fixes a bug in the
Select
component related to searched values that were automatically being selected without an explicit selection from the user. This happens because the onChange event is called when a value selection is made or when the input changes. This was only perceived with the introduction ofautoClearSearchValue={false}
in #23869. This PR changes the logic to only fire theonChange
event when there's an actual selection by the user.TESTING INSTRUCTIONS
I added a test to the component but we need to check the general use of selects in the application because there are wrappers that override the component behavior such as
SelectControl
andSelectFilterPlugin
.ADDITIONAL INFORMATION