CustomSelectControl: Use key to determine the selected item instead of name#72189
CustomSelectControl: Use key to determine the selected item instead of name#72189arthur791004 merged 6 commits intotrunkfrom
Conversation
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
131df7a to
416d16c
Compare
|
Flaky tests detected in 0bec13d. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/19122253270
|
aduth
left a comment
There was a problem hiding this comment.
This change makes sense to me 👍 It's also more consistent with documented examples. It might be nice to include a regression test for what we're trying to fix here.
| renderSelectedValue={ | ||
| showSelectedHint ? renderSelectedValueHint : undefined | ||
| } |
There was a problem hiding this comment.
Why did we change the logic here? It seemed like this was a simplification to avoid rendering the <Styled.SelectedExperimentalHintWrapper> wrapper if we don't intend to show the selected hint?
There was a problem hiding this comment.
We now need the render function because the value becomes the key of the options. I pushed changes to avoid rendering the wrapper by a0f4a6e.
| <VisuallyHidden> | ||
| <span id={ descriptionId }> | ||
| { getDescribedBy( currentValue, describedBy ) } | ||
| { getDescribedBy( selectedOption.name, describedBy ) } |
There was a problem hiding this comment.
Minor: The function argument is still named currentValue even though we're passing the name here, which could be confusing with how we're now associating "value" with "key" elsewhere (and key not being the same as name).
416d16c to
a0f4a6e
Compare
| { currentValue } | ||
| { selectedOptionHint && ( | ||
| { selectedOption.name } | ||
| { showSelectedHint && selectedOption.hint && ( |
There was a problem hiding this comment.
With the changes in 516f9d1, this code could never be reached without the condition being satisfied, right?
| { showSelectedHint && selectedOption.hint && ( |
There was a problem hiding this comment.
Forgot to remove it 🤦♂️ Done by 434b6c7.
a04c490 to
434b6c7
Compare
|
|
||
| const renderSelectedValue = () => { | ||
| if ( ! showSelectedHint || ! selectedOption.hint ) { | ||
| return selectedOption.name; |
There was a problem hiding this comment.
I'm surprised that TypeScript doesn't raise an issue here, since I think selectedOption could be undefined if the options array is empty (i.e. options[ 0 ] would be undefined if options is an empty array). It'd be pretty unconventional usage, but we're doing safe property access above, so maybe we should here as well:
There was a problem hiding this comment.
Oh yes, you're right! Fixed by 0bec13d.
This is because:
- For an array type T[], TypeScript defines the indexed access type T[]["0"] as simply T.
- It doesn't try to analyze if the array could be empty at runtime.
- So it trusts that "options is an array of T, so options[0] is of type T".
We have to enable below to force TS raises the value is probably undefined.
{
"compilerOptions": {
"noUncheckedIndexedAccess": true
}
}There was a problem hiding this comment.
Nice sleuthing, that makes sense.
I think that TypeScript option could make sense to enable, though I might fear it could introduce a whole bunch of new issues to work through.
|
Thanks for the review! |
What?
If the options have duplicate name, then all of them will be shown as the selected item when any of them is selected. For example, if you have a list of the pages as below, and you want to use the
CustomSelectControl, then it makes the result becomes weird.Why?
The "key" property should be the unique value in the options. As a result, we should use "key" to determine whether the item is selected to ensure there is only one selected item. Otherwise, if a list has options with the same name, all of them will be shown as selected item.
How?
Replace any condition that checks the selected item using its
nameproperty so that it instead uses thekeyproperty. The onChange event now passes the entire selectedItem, ensuring backward compatibility with no breaking changesTesting Instructions
Storybook
Editor
Testing Instructions for Keyboard
Screenshots or screencast