A Simple and fully customizable to handle Form in React Native. This library inspired by Formik.
You can check Example code in this link
- Auto scroll to first error field
- Manage, track state & values of fields
- Supports validations using yup
- Supports custom components
you can install using npm:
npm i rn-auto-scroll-form
import { FormController } from 'rn-auto-scroll-form';create validation using yup
const schema = yup.object().shape({
email: yup.string().email().required(),
password: yup.string().min(6).required(),
});<FormController
initialValue={{email: '', password: ''}}
validationSchema={schema}
onSubmit={({isValid, values, firstErrAt}) => console.warn(values)}>
{({
values,
errors,
refs,
handleChange,
handleBlur,
handleSubmit,
}) => {
return (
<View style={styles.content}>
<TextInput
ref={refs?.email}
style={styles.textInput}
placeholder="Email"
onChangeText={handleChange('email')}
onBlur={handleBlur('email')}
value={values?.email}
/>
{!!errors.email && <Text>{errors.email}</Text>}
<TextInput
ref={refs?.password}
style={styles.textInput}
placeholder="Password"
onChangeText={handleChange('password')}
onBlur={handleBlur('password')}
value={values?.password}
/>
{!!errors.password && <Text style={styles.errText}>{errors.password}</Text>}
<Button onPress={handleSubmit} title="Submit" />
</View>
);
}}
</FormController>import { useFormController, ScrollableView, Field } from 'rn-auto-scroll-form'; const schema = yup.object().shape({
email: yup.string().email().required(),
password: yup.string().min(6).required(),
});
const myform = useFormController({
initialValues: initialValue,
enableReinitialize: true,
validationSchema: schema,
onSubmit: ({isValid, values, firstErrAt}) => {
console.log({isValid, values, firstErrAt});
},
});<ScrollableView ref={myform?.controller}>
<View style={styles.content}>
<Text
style={
styles.title
}>{`${myform?.count?.count}/${myform?.count?.total}`}</Text>
<Field component={MyField} label="Email" name="email" form={myform} />
<Field component={MyField} label="Password" name="password" form={myform} />
...
<Button onPress={myform.handleSubmit} title="Submit" />
</View>
</ScrollableView>this is example of custom component, make sure your custom component have props onChangeText onBlur value error (optional)
export const MyField = props => {
const {style, error, label, ...otherProps} = props;
return (
<>
<Text>{label}</Text>
<TextInput style={[styles.textInput, style]} {...otherProps} />
{!!error && <Text style={styles.errText}>{error}</Text>}
</>
);
};import { FormController, Field } from 'rn-auto-scroll-form';you dont need to handle onChangeText, etc anymore. that is handle at Field Wrapper Component
<FormController
initialValue={{email: '', password: ''}}
validationSchema={schema}
onSubmit={({isValid, values, firstErrAt}) => console.warn(values)}>
{({
handleSubmit,
}) => {
return (
<View style={styles.content}>
<Field
label="Email"
placeholder="Input your email"
name="name"
component={MyField}
/>
<Field
label="Password"
placeholder="Input your password"
component={MyField}
/>
<Button onPress={handleSubmit} title="Submit" />
</View>
);
}}
</FormController>you can create wrapper component for your component that dont have props onChangeText onBlur value.
in this example you need to get all data with useContext(FormContext) and mapping to your custom component value errText onChangeValue.
make sure your custom component have props name or whatever your naming that prop (to handle getting specific data)
import { FormContext } from 'rn-auto-scroll-form';
export const YourWrapField = ({ component: Component, name, ...props }) => {
const ctx = useContext(FormContext);
return (
<View style={{ width: '100%' }} ref={ctx?.refs[name]}>
<Component
value={ctx?.values[name]}
errText={ctx?.errors[name]}
onChangeValue={ctx?.handleChange(name)}
{...props}
/>
</View>
)
}Props
| Property | Required | Type | Default |
|---|---|---|---|
| children | yes |
((context: FormContext) => React.ReactNode) |
- |
| initialValues | yes |
Values |
- |
| validationSchema | No |
`Schema | (() => Schema)` |
| validateOnBlur | No |
bool |
true |
| validateOnChange | No |
bool |
false |
| enableReinitialize | No |
bool |
false |
| countRequiredOnly | No |
bool |
true |
| autoscroll | No |
bool |
true |
| countingFields | No |
Array[String] |
null |
Params when using useFormController
type UseFormParams<T> = {
initialValues: T;
validationSchema: any;
onSubmit: (params: SubmitParams<T>) => void;
countRequiredOnly?: boolean;
countingFields?: string[];
validateOnChange?: boolean;
validateOnBlur?: boolean;
enableReinitialize?: boolean;
autoscroll?: boolean;
};params onSubmit
type SubmitParams<T> = {
isValid: boolean;
values: GenericObj<T>;
firstErrAt?: string | null;
};Form Context
interface FormContext<T> {
values: T;
errors?: T;
count: Count;
refs?: T;
controller: React.Ref<ScrollableView>;
handleChange: (txt: string) => void;
handleBlur: (txt: string) => void;
handleSubmit: (refs: T) => void;
}
interface Count {
count: number;
total: number;
}you can use TextInputProps at Field Component
| Property | Required | Type |
|---|---|---|
| name | yes |
string |
Pull requests are always welcome! Feel free to open a new GitHub issue for any changes that can be made.
Working on your first Pull Request? You can learn how from this free series How to Contribute to an Open Source Project on GitHub
Egi Wibowo | egiwibowo13
