Managing form values, validation, focus & submission is kind of boring & pain we all know that. But if we can centralise that form management stuff to one package, that will be good enough for developer to think and develop something important than this.
Don't reapeat yourself is a thing, There are many plugins available at ease, But...
The plugins i have seen before are more into react oriented than the react native. like formik, it dont have anything specific binder to react-native, again we have to give all values or hndling functions separately & again we need to manage focus in our code.
A solution - react-formr
So here we go with react-formr, a package is written for react native.
Features
- Form validation on given rules (regex) or predefined types(email, phone, etc).
- Input binder function includes almost everything
TextInput
required to handle form. - Auto focus next available input on return press, triggering
onFocuseFinish
on last input return key press. - Input blur validation & validate on change of invalid input.
- Listen to live changes in form using
onChange
props. - Written with Typescript
- Not limited to TextInput, it can be used anything with handle value change & values object.
Update:
useFormr
hook is available now, no need to wrap the form with Formr component anymore.
Let's jump into using it
first & foremost - installation
yarn add react-formr
or npm install react-formr
react-formr
A big one
Form with complete available options from formr
// Formr form manager wrapper
<Former
onChange={(values)=>{
// Triggers if any value change in form
console.log(values)
}}
onFinishFocus={(values)=>{
// Triggers all form fields finished focusing
console.log(values)
}}
formFields={{ password: "" }} //Initial value can be added here
validation={{
password: {
required: true,
rules:
"0-9])(?=.*[a-z].*[a-z].*[a-z]).{8}$",
}
}} >
{// Provides a function to render form inputs }
{({
inputBinder, // Package of TextInput props
onChangeHandler, // included in inputBinder
values, // included in inputBinder
onBlurHandler,// included in inputBinder
onSubmitHandler,
onSubmitEditingHandler,
refsHandler,// included in inputBinder
touched,// included in inputBinder if you are making custom input component with this props
valid,// included in inputBinder if you are making custom input component with this props
}) => {
return (
<View
style={{
flex: 1,
marginTop: 50,
}}>
<TextInput
style={{
borderColor:
valid.email != null && touched.email && !valid.email
? "red"
: "black",
...styles.input,
}}
value={values.password}
ref={(ref)=>refsHandler('password',ref)}
onBlur={() => onBlurHandler('password')}
onChangeText={text=>onChangeHandler('password',text)}
onSubmitEditing={()=>onSubmitEditingHandler('password')}
/>
<Button onPress={()=>onSubmitHandler(value=>submitIt(value))} />
</View>
)//end of return
}// end of formr function
}
</Formr>
Shorter version
Using only Formr's inputBinder function
<Former formFields={{ password: "" }}
validation={{
password: {
required: true,
rules:
"0-9])(?=.*[a-z].*[a-z].*[a-z]).{8}$",
}
}} >
{({
inputBinder,
onSubmitHandler,
touched,
valid
}) => {
return (
<View
style={{
flex: 1,
marginTop: 50,
}}>
<TextInput
style={{
borderColor:
valid.email != null && touched.email && !valid.email
? "red"
: "black",
...styles.input,
}}
{...inputBinder("email")} // THIS IS WHERE THE DIFFERENCE COMES
/>
<Button
onPress={()=>onSubmitHandler(value=>submitIt(value))}
/>
</View>
)//end of return
}// end of formr function
}
</Formr>
My Shortest version
The shortest & easiest version is to make a custom input component with error handled inside it.
CustomInput component with error message
const CustomInput = React.forwardRef(({valid,value,touched,errorMsg,...rest},ref)=>{
const showError = value!=="" && valid && touched;
return(
<View>
<TextInput
{...rest}
ref={ref}
value={value}
style={
borderWidth:1,
borderColor:showError?"red":"gray",
...rest.style}
/>
{showError && <Text style={color:"red"} >{errorMsg}</Text>}
</View>
})
Formr form with CustomInput
<Former formFields={{ email: "" }}
validation={{
password: {
required: true,
type:"email"
}
}} >
{({
inputBinder, // Package of TextInput props.
onSubmitHandler, // For submitting form.
}) => {
return (
<View
style={{
flex: 1,
marginTop: 50,
}}>
<CustomInput
{...inputBinder("email")}
errorMessage="Something is wrong here"
/>
<Button onPress={()=>onSubmitHandler(value=>submitThis(value))} />
</View>
)//end of return
}// end of formr function
})
</Formr>
Is't it easy??
The Standouts
inputBinder
This function includes almost everything for TextInput
to manage form with inputs, They are - value
, onChangeText
, onBlur
, ref
, onSubmitEditing
also valid
& touched
if you are making custom input component with these props .
validation
Receives object with predefined commonly used type or regex rules to validate, also we can mention required field here, Option of providing rules to the input is unlimited with regex.
Auto focusing input
Unlike react form plugins, as it is built for react-native, it handles focusing next input (or the element have ref & handles focus) easily. Let's see more about this in next topic.
Common problems & solutions
Auto focusing next input with ref
The best user experience is to focus next available input on next button press in already visible keyboard, Nobody wants to touch all available inputs to fill the form. that is kind of must for all forms now. The problem here to manage refs of input & focusing them with onSubmitEditing
.
Formr solves this hassle by maintaining refs inside it & focusing next ref on submitHandler.
Managing Validation
Yes, Managing validation with multiple input will go very long or unexpectedly complicated. Every field with its own type of validation handling, need to handle touched states to show error after interaction, it will become hefty if we don't plan it properly.
Formr has the thing what we don't want to write it again & again. One package handles touch state management, validation cycles, focus events for validations & so on. it also validates fields on any value change or submit press, updates valid object, it focuses untouched input fields.
Managing form values
We might need to maintain multiple states for input values, that is kind of too much if we are trying to make a function to update all & validate.
Formr receives initial values, manages it on update of any form fields, provides values object in multiple places, i.e. in form render function as values, in onSubmit
, in onFinishFocus
prop, in onChange
prop.
Final
While i was working with my projects, i felt that I'm writing something repeatedly & unnecessarily. If i try to go for any plugins to do it, has its own learning curve & road blocks or i have to use multiple plugin to do 1 form, that is little too much to handle later. So this, I have created a package to share with everyone of you. Suggest me if anything i can improve in this.
NPM
react-formr
Github
react-formr
my github profile
Top comments (0)