rn-auto-scroll-form
A Simple and fully customizable to handle Form in React Native. This library inspired by Formik.
Example
You can check Example code in this link
Features
- Auto scroll to first error field
- Manage, track state & values of fields
- Supports validations using yup
- Supports custom components
Getting Started
Installation
you can install using npm:
npm i rn-auto-scroll-form
Usage
Basic Usage
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>
Function useFormController
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>
Custom Component
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>
Create Custom Wrapper Component
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>
)
}
API Reference
FormController
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 |
useFormController
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;
};
FormContext
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;
}
Field
you can use TextInputProps at Field Component
Property | Required | Type |
---|---|---|
name | yes |
string |
Contributing
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
Author
Egi Wibowo | egiwibowo13