RHFSelect
Select dropdown component integrated with React Hook Form
You are reading the v1 docs. v2 renamed several props and replaced GeckoUIPortal with GeckoUIProvider. Read this page in v2.
Live examples are only rendered in the v2 docs.
RHFSelect
A select dropdown component integrated with React Hook Form that automatically displays error states with a red border when validation fails. Supports both single and multiple selection modes with keyboard navigation and search capabilities.
Installation
import { RHFSelect, SelectOption } from '@geckoui/geckoui';Basic Usage
import { useForm, FormProvider } from 'react-hook-form';
import { RHFSelect, SelectOption } from '@geckoui/geckoui';
function Example() {
const methods = useForm({
defaultValues: {
basicCountry: ''
}
});
return (
<FormProvider {...methods}>
<RHFSelect name="basicCountry" placeholder="Select a country">
<SelectOption value="us" label="United States" />
<SelectOption value="uk" label="United Kingdom" />
<SelectOption value="ca" label="Canada" />
<SelectOption value="au" label="Australia" />
<SelectOption value="de" label="Germany" />
</RHFSelect>
</FormProvider>
);
}Props API
Extends all props from Select component plus:
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | - | Field name (required) |
control | Control | Auto-injected | Optional: Pass explicitly for nested forms or custom form context |
rules | RegisterOptions | - | Inline validation rules |
multiple | boolean | false | Enable multiple selection mode |
children | SelectOption[] | - | SelectOption components to render as dropdown options |
onChange | (value: T | T[]) => void | - | Change callback (receives value based on single/multiple mode) |
className | string | - | Additional CSS class for the select button |
wrapperClassName | string | - | Additional CSS class for the wrapper div |
placeholder | string | - | Placeholder text when no value is selected |
disabled | boolean | false | Disable the select input |
| ...rest | SelectProps | - | All Select component props |
Examples
With Validation (Zod)
import { useForm, FormProvider } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { RHFSelect, SelectOption, RHFInputGroup } from '@geckoui/geckoui';
const schema = z.object({
validationSkills: z.string().min(1, 'Please select at least one skill')
});
function Example() {
const methods = useForm({
resolver: zodResolver(schema),
mode: 'onBlur',
defaultValues: {
validationSkills: ''
}
});
return (
<FormProvider {...methods}>
<RHFInputGroup label="Primary Skill" required>
<RHFSelect name="validationSkills" placeholder="Select your skill">
<SelectOption value="js" label="JavaScript" />
<SelectOption value="ts" label="TypeScript" />
<SelectOption value="react" label="React" />
<SelectOption value="vue" label="Vue" />
<SelectOption value="angular" label="Angular" />
</RHFSelect>
</RHFInputGroup>
</FormProvider>
);
}Multiple Selection
Enable multiple selection mode to allow users to select multiple options:
import { useForm, FormProvider } from 'react-hook-form';
import { RHFSelect, SelectOption } from '@geckoui/geckoui';
function Example() {
const methods = useForm({
defaultValues: {
multipleLanguages: []
}
});
return (
<FormProvider {...methods}>
<RHFSelect name="multipleLanguages" multiple placeholder="Select languages">
<SelectOption value="en" label="English" />
<SelectOption value="es" label="Spanish" />
<SelectOption value="fr" label="French" />
<SelectOption value="de" label="German" />
<SelectOption value="zh" label="Chinese" />
<SelectOption value="ja" label="Japanese" />
</RHFSelect>
</FormProvider>
);
}With Option Groups
Organize options into logical groups:
<RHFSelect name="groupedCategory" placeholder="Select a category">
<SelectOption value="electronics" label="Electronics" />
<SelectOption value="computers" label="Computers" />
<SelectOption value="phones" label="Phones" />
<SelectOption value="clothing" label="Clothing" />
<SelectOption value="shoes" label="Shoes" />
<SelectOption value="accessories" label="Accessories" />
</RHFSelect>Disabled State
<RHFSelect name="disabledStatus" disabled placeholder="Status">
<SelectOption value="active" label="Active" />
<SelectOption value="inactive" label="Inactive" />
<SelectOption value="pending" label="Pending" />
</RHFSelect>With onChange Callback
Execute custom logic when the selection changes:
<RHFSelect
name="callbackPriority"
placeholder="Select priority"
onChange={(value) => {
console.log('Selected priority:', value);
}}
>
<SelectOption value="low" label="Low" />
<SelectOption value="medium" label="Medium" />
<SelectOption value="high" label="High" />
<SelectOption value="urgent" label="Urgent" />
</RHFSelect>Complete Form Example
import { useForm, FormProvider } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { RHFSelect, SelectOption, RHFInputGroup, Button } from '@geckoui/geckoui';
const schema = z.object({
formCountry: z.string().min(1, 'Country is required'),
formLanguages: z.array(z.string()).min(1, 'Select at least one language'),
formPriority: z.string().min(1, 'Priority is required')
});
function RegistrationForm() {
const methods = useForm({
resolver: zodResolver(schema),
mode: 'onBlur',
defaultValues: {
formCountry: '',
formLanguages: [],
formPriority: ''
}
});
return (
<FormProvider {...methods}>
<form onSubmit={methods.handleSubmit(console.log)}>
<RHFInputGroup label="Country" required>
<RHFSelect name="formCountry" placeholder="Select your country">
<SelectOption value="us" label="United States" />
<SelectOption value="uk" label="United Kingdom" />
<SelectOption value="ca" label="Canada" />
</RHFSelect>
</RHFInputGroup>
<RHFInputGroup label="Languages" required>
<RHFSelect name="formLanguages" multiple placeholder="Select languages">
<SelectOption value="en" label="English" />
<SelectOption value="es" label="Spanish" />
<SelectOption value="fr" label="French" />
</RHFSelect>
</RHFInputGroup>
<RHFInputGroup label="Priority" required>
<RHFSelect name="formPriority" placeholder="Select priority">
<SelectOption value="low" label="Low" />
<SelectOption value="medium" label="Medium" />
<SelectOption value="high" label="High" />
</RHFSelect>
</RHFInputGroup>
<Button type="submit">Submit</Button>
</form>
</FormProvider>
);
}Inline Rules Validation
For simple validation, use the rules prop:
<RHFSelect
name="country"
placeholder="Select a country"
rules={{ required: 'Please select a country' }}
>
<SelectOption value="us" label="United States" />
<SelectOption value="uk" label="United Kingdom" />
</RHFSelect>For complex forms, we recommend using a schema resolver (Zod, Yup) instead.
Single vs Multiple Mode
RHFSelect supports two selection modes:
Single Select (Default)
const methods = useForm({
defaultValues: {
country: ''
}
});
<RHFSelect name="country">
<SelectOption value="us" label="United States" />
<SelectOption value="uk" label="United Kingdom" />
</RHFSelect>In single select mode:
- Value is a single item of type
T - Clicking an option selects it and closes the menu
- Only one option can be selected at a time
Multiple Select
const methods = useForm({
defaultValues: {
languages: []
}
});
<RHFSelect name="languages" multiple>
<SelectOption value="en" label="English" />
<SelectOption value="es" label="Spanish" />
</RHFSelect>In multiple select mode:
- Value is an array of type
T[] - Clicking an option toggles its selection
- Menu stays open after selection
- Multiple options can be selected
Validation
Use Zod schema validation for form validation:
const schema = z.object({
singleSelect: z.string().min(1, 'This field is required'),
multipleSelect: z.array(z.string()).min(1, 'Select at least one option')
});For more complex validation:
const schema = z.object({
skills: z
.array(z.string())
.min(2, 'Select at least 2 skills')
.max(5, 'Select no more than 5 skills')
});Tip: Use mode: 'onBlur' in useForm to validate when the user leaves the field:
const methods = useForm({
resolver: zodResolver(schema),
mode: 'onBlur'
});Error States
RHFSelect automatically displays error states with:
- Red border via
data-errorattribute on the root element whenfieldState.errorexists - No automatic error message display (use RHFInputGroup or RHFError component)
.GeckoUIRHFSelectButton[data-error] {
border-color: red;
}Use RHFInputGroup component for label + select + error layout:
<RHFInputGroup label="Country" required>
<RHFSelect name="country">
<SelectOption value="us" label="United States" />
</RHFSelect>
</RHFInputGroup>Or combine with RHFError component manually:
<RHFSelect name="country">
<SelectOption value="us" label="United States" />
</RHFSelect>
<RHFError name="country" />Accessibility
- Full keyboard navigation support (Arrow keys, Enter, Escape)
- Built-in search/filter functionality
- Proper ARIA attributes for error states
- Screen reader compatible
- Focus management with visual indicators
Related Components
- Select - Base select component
- SelectOption - Individual option component
- RHFInputGroup - Label and error wrapper
- RHFError - Error message display