Skip to content

Instantly share code, notes, and snippets.

@vladi-strilets
Last active December 15, 2023 19:18
Show Gist options
  • Save vladi-strilets/5da9c980e9f9689ef362b70784e4db0c to your computer and use it in GitHub Desktop.
Save vladi-strilets/5da9c980e9f9689ef362b70784e4db0c to your computer and use it in GitHub Desktop.
Custom reusable controller for react-hook-form and TypeScript + NativeBase
import { FormControl, Input } from 'native-base'
import React from 'react'
import {
Control,
Controller,
FieldError,
Path,
RegisterOptions,
} from 'react-hook-form'
interface FormInputControllerProps<FieldsType> {
name: Path<FieldsType>
defaultValue?: string
rules?: RegisterOptions
error?: FieldError
control: Control<FieldsType>
}
interface Props<FieldsType> extends FormInputControllerProps<FieldsType> {
label?: string
placeholder?: string
}
const FormInputController = <FieldsType,>({
error,
rules,
label,
control,
name,
placeholder,
}: Props<FieldsType>) => {
const isInvalid = error != null
const isRequired = rules != null && 'required' in rules
return (
<FormControl isInvalid={isInvalid} isRequired={isRequired}>
{label != null && <FormControl.Label>{label}</FormControl.Label>}
<Controller
control={control}
name={name}
render={({ field: { onChange, onBlur, value } }) => (
<Input
placeholder={placeholder}
value={value}
onBlur={onBlur}
onChangeText={(val) => onChange(val)}
/>
)}
rules={rules}
/>
{error != null && (
<FormControl.ErrorMessage>
{error.message}
</FormControl.ErrorMessage>
)}
</FormControl>
)
}
export default FormInputController
{
"dependencies": {
"native-base": "^3.2.1",
"react": "17.0.2",
"react-hook-form": "^7.17.5",
"react-native": "0.66.0",
},
}
import { Button, VStack } from 'native-base'
import React from 'react'
import { useForm } from 'react-hook-form'
import FormInputController from '~components/FormInputController/FormInputController'
import { validateEmail } from '~utils/validations'
enum FormFields {
email = 'email',
}
type FormData = {
email: string
}
const ResetPasswordForm: React.FC = () => {
const {
control,
handleSubmit,
formState: { errors },
} = useForm<FormData>()
const onSubmit = handleSubmit((data) => console.log(data))
return (
<VStack>
<FormInputController
control={control}
error={errors.email}
label={'Label'}
name={FormFields.email}
rules={{
required: 'Is required',
validate: (value) =>
validateEmail(value) || 'Use a valid email',
}}
/>
<Button mt="2" onPress={onSubmit}>
{'Send link'}
</Button>
</VStack>
)
}
export default ResetPasswordForm
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment