Skip to content

Instantly share code, notes, and snippets.

@alanfoandrade
Created August 22, 2021 17:59
Show Gist options
  • Save alanfoandrade/2c8b30d426e0198351c54212f6390ee9 to your computer and use it in GitHub Desktop.
Save alanfoandrade/2c8b30d426e0198351c54212f6390ee9 to your computer and use it in GitHub Desktop.
react-select (async) with chakra and react-hook-forms
import {
FormLabel,
FormControl,
FormErrorMessage,
useTheme,
} from '@chakra-ui/react';
import { Control, Controller, FieldError } from 'react-hook-form';
import { OptionTypeBase, StylesConfig } from 'react-select';
import ReactAsyncSelect, { AsyncProps } from 'react-select/async';
interface ISelectProps extends AsyncProps<OptionTypeBase> {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
control: Control<any>;
name: string;
label?: string;
error?: FieldError;
onInputChange: (inputValue: string) => void;
}
export const AsyncSelect = ({
name,
control,
onInputChange,
label,
error,
...rest
}: ISelectProps): JSX.Element => {
const theme = useTheme();
const customStyles: StylesConfig<
{
label: string;
value: string;
},
false
> = {
menu: (provided) => ({
...provided,
borderRadius: theme.radii.md,
padding: 15,
}),
control: (provided) => ({
...provided,
backgroundColor: theme.colors.gray[100],
borderRadius: theme.radii.md,
height: 48,
padding: '0 4px',
}),
dropdownIndicator: (provided) => ({
...provided,
color: theme.colors.gray[700],
}),
indicatorSeparator: (provided) => ({
...provided,
display: 'none',
}),
option: (provided, state: { isSelected: boolean }) => ({
...provided,
borderRadius: theme.radii.md,
color: state.isSelected ? 'white' : theme.colors.gray[700],
padding: '10px 20px',
marginBottom: 4,
cursor: 'pointer',
}),
};
return (
<FormControl isInvalid={!!error}>
{!!label && <FormLabel htmlFor={name}>{label}</FormLabel>}
<Controller
name={name}
control={control}
render={({ field: { onChange, onBlur } }) => (
<ReactAsyncSelect
cacheOptions
onChange={(e) => onChange(e?.value)}
onBlur={onBlur}
onInputChange={onInputChange}
loadOptions={onInputChange}
getOptionValue={(option) => option.value}
getOptionLabel={(option) => option.label}
styles={customStyles}
noOptionsMessage={({ inputValue }) =>
!inputValue ? 'Começe a digitar...' : 'Nenhum encontrado'
}
placeholder=""
/>
)}
{...rest}
/>
{!!error && (
<FormErrorMessage position="absolute">{error.message}</FormErrorMessage>
)}
</FormControl>
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment