Last active
June 8, 2020 09:40
-
-
Save janjakubnanista/323a1731c8acb9f8d346c3bdcbf47e01 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Approach 3: The compromise | |
// | |
// We will add both labelFromValue and itemComponent props to our Select | |
export interface SelectProps<T> { | |
// ... previous props | |
itemComponent: React.ComponentType<SelectItemProps<T>>; | |
labelFromValue: (value: T) => React.ReactNode; | |
} | |
// We will keep the itemComponent props from before, the only extra thing | |
// that we add is the children prop. | |
// | |
// (React actually adds the children prop automatically, I am only doing this | |
// to be extra explicit) | |
export interface SelectItemProps<T> { | |
children: React.ReactNode; | |
selected: boolean; | |
value: T; | |
onToggle: (value: T) => void; | |
} | |
export function Select<T>({ items, value, idFromValue, labelFromValue, itemComponent: ItemComponent, onChange }: SelectProps<T>) { | |
const selectedId = value === undefined ? undefined : idFromValue(value); | |
const isSelected = (id: string | number) => id === selectedId; | |
const handleToggle = (value: T) => onChange?.(isSelected(idFromValue(value)) ? undefined : value); | |
return <div> | |
{items.map(item => { | |
const id = idFromValue(item); | |
const selected = isSelected(id); | |
// The item label comes from the labelFromValue prop | |
const label = labelFromValue(item); | |
// And the UI and UX comes from the itemComponent | |
return <ItemComponent key={id} value={item} selected={selected} onToggle={handleToggle}> | |
{label} | |
</ItemComponent>; | |
})} | |
</div>; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment