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