The API contract needs to be cohesive
Problem
Today I refactored a React component that allows:
- selecting from a list of options
- create a new option if you can't find what you looked for in the list of options
Live example here
The initial implementation was based off an example found on the Material UI documentation website. Link here
// Before refactoringtype OptionType = {label: string, value: string}type ComboBoxProps = {options: OptionType[],onValueChange: string => null}ComboBox: FC<ComboBoxProps> = ({label,options,onValueChange,}) => {/*implementation here*/}
I had 2 issues with it
the API (aka props) wasn't cohesive
You passed in a list of options but the callback is named onValueChange. I would reuse the concept of the option given it's already used in the options array
the API didn't provide what the user of this component would expect
This component needs 2 event handlers:
- event 1: when you select an existing option
- event 2: when you create a new option
Reasons for 2 event handlers:
- The user of this component will likely need to distinguish between these 2 events. When user creates a new option (i.e. event 2) the developer will likely need to make a backend call to create this option If you provide only 1 event handler then the developer using the combobox will need to handle that logic himself
- having 2 event handlers documents what the purpose is of the react component. By having 2 event handlers onCreate and onSelect you emphasise the use case for this React component (i.e. select or create in 1 component)
// After refactoringtype OptionType = {label: string, value: string}type ComboBoxProps = {options: OptionType[],onOptionSelect: OptionType => null,onOptionCreate: OptionType => null}ComboBox: FC<ComboBoxProps> = ({label,options,onOptionSelect,onOptionCreate}) => {/*implementation here*/}