docs: select field custom component example fixed and improved
Description
I discovered a few things in this documentation code snippet that cost me time to figure out. I think the improvements are valid for most users.
There were also minor errors that needed fixing.
Fixes:
- A typo where
CustomSelectPropswas declared incamelCasebut referenced inPascalCase. - The callback value in
onChangeis potentiallynull, e.g., when clearing the select.
Regarding the onChange parameter, I think we should also change the Interface to add null:
export type SelectInputProps = Omit<SelectField, 'options' | 'type' | 'value'> & {
// …
onChange?: (value: Option|null) => void
// …
}
Please let me know how to proceed with this one :)
Improvements:
- Typescript types clarifying the expected output of the
.filterfunction. - CSS classes as used in the default UI to make the example a drop-in replacement. We could also use
fieldBaseClasshere.
- [x] I have read and understand the CONTRIBUTING.md document in this repository.
Type of change
- [x] This change requires a documentation update
Checklist:
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] Existing test suite passes locally with my changes
- [ ] I have made corresponding changes to the documentation
@barthy-koeln this all looks great 👍 except I don't think we should include null in the onChange handler because it does not match the function's type. If you can revert that change then I think this is mergable. Looks like it was missing the argument, though.
For the record to use null you should include an option with the value of null to achieve this.
@jacobsfletch
The issue is that ReactSelect has null in its type definition and its documentation:
onChange = (
newValue: OnChangeValue<Option, IsMulti>,
actionMeta: ActionMeta<Option>
)
export type OnChangeValue<Option, IsMulti extends boolean> = IsMulti extends true
? MultiValue<Option>
: SingleValue<Option>
export type SingleValue<Option> = Option | null;
They use it when clearing the select, for example using the built-in clear button that is enabled in Payload UI by default:
clearValue = () => {
const { selectValue } = this.state;
this.onChange(valueTernary(this.props.isMulti, [], null), {
action: 'clear',
removedValues: selectValue,
});
};
Which means that the current example for a custom select in the Payload docs throws errors when clearing the input.
onChange={(o) => setValue(o.value)}
react-dom.development.js:4312 Uncaught TypeError: Cannot read properties of null (reading 'value') at onChange (IconSelectComponent.tsx:61:123) at useStateManager-7e1e8489.esm.js:36:7 at Select2._this.onChange (Select-aecb2a80.esm.js:1177:7) at Select2._this.clearValue (Select-aecb2a80.esm.js:1251:13) at Select2._this.onClearIndicatorMouseDown (Select-aecb2a80.esm.js:1378:13) …
Ok interesting, thank you for pointing this out. I think the move here then is to adjust the Payload types accordingly to match React Select. I would expect that TS is throwing an error in your onChange handler because Option is never null according to Payload. Are you getting any type errors from your change?
No, interestingly it doesn't throw any errors for comparisons with null and undefined, even with strictNullChecks.
Here's a simplified example
const num: number = 3
if (num === null) {
console.info('this one is fine')
}
if (num === 'string') {
console.info('this one is not')
}
See the output in the TypeScript Playground.
Should I extend this PR to also adapt the types?
@jacobsfletch just a careful ping to see if I can further support here.
Docs will be reworked for 3.0. Feel free to PR after release.