Introduction
React Native doesn’t have a native <form> element, and managing the state of multiple inputs can be verbose. That’s why I’ll show you a simple way to handle forms using Formik and Yup. Once you get the hang of it, you’ll be able to build more complex forms with ease.
Prerequisites
- Expo CLI installed (docs)
- Basic React Native knowledge
- Wrap your app with React Native Paper’s
<PaperProvider>(docs)
Setup
npx create-expo-app my-formik-form
cd my-formik-form
npm install formik react-native-paper yup
How does Formik with React Native work
1. Import dependencies
app/components/MyForm.tsx
import { Formik } from "formik"
import { View } from "react-native"
import { TextInput, Text, Button, HelperText } from "react-native-paper"
import * as Yup from "yup"
2. Wrap your form with Formik
Since React Native doesn’t have a native <form>, wrap your component with <Formik>.
app/components/MyForm.tsx
export default function MyForm() {
return (
<Formik {...requiredProps}>
{/* form goes here */}
</Formik>
)
}
3. Add necessary props
Formik needs at least two props: initialValues and onSubmit.
<Formik
initialValues={{
email: "",
password: ""
}}
onSubmit={values => console.log(values)}
>
{/* rest of the form */}
</Formik>
4. Use Formik’s callback
Formik exposes several helper methods that make your form work:
- handleChange(field) – updates state on input
- handleBlur(field) – marks field as touched
- handleSubmit() – calls your
onSubmit - values – current form state
<Formik {...requiredProps}>
{({
handleChange,
handleBlur,
handleSubmit,
values
}) => (
<View>
{/* email input */}
<TextInput
value={values.email}
onChangeText={handleChange("email")}
onBlur={handleBlur("email")}
/>
{/* password input */}
<TextInput
secureTextEntry
value={values.password}
onChangeText={handleChange("password")}
onBlur={handleBlur("password")}
/>
<Button onPress={handleSubmit}>
Login/Register
</Button>
</View>
)}
</Formik>
✅ You’ve got your first working form!
⚠️ But:
-
There are no labels: users won’t know what to enter.
-
There’s no validation: users don’t get any feedback.
“Is that my name or should I enter my credit card number?”
Adding Labels
Add the label prop to each <TextInput />.
<TextInput
label="Email" // ✅ add this
value={values.email}
onChangeText={handleChange("email")}
onBlur={handleBlur("email")}
/>
<TextInput
label="Password" // ✅ add this
secureTextEntry
value={values.password}
onChangeText={handleChange("password")}
onBlur={handleBlur("password")}
/>
Adding Validation with Yup
To validate user input, we’ll use Yup, a JavaScript schema builder for value parsing and validation.
It works great with Formik to define field requirements like required inputs, length, format, and patterns.
Create validation schema
const SignupSchema = Yup.object().shape({
email: Yup.string()
.email("Invalid email.")
.required("Required"),
password: Yup.string()
.min(6, "Too Short")
.max(30, "Too Long")
.matches(
/^(?=.*[A-Za-z])(?=.*\d).+$/,
"Password must contain at least one letter and one number"
)
.required("Required")
})
Add schema to Formik
<Formik
validationSchema={SignupSchema} // ✅ add this
initialValues={{
email: "",
password: ""
}}
onSubmit={values => console.log(values)}
>
{/* rest of the form */}
</Formik>
Add validation props
<Formik {...requiredProps}>
{({
handleChange,
handleBlur,
handleSubmit,
values,
errors, // ✅ add
touched // ✅ add
}) => (
<View>
{/* inputs go here */}
</View>
)}
</Formik>
Add error props to inputs
<TextInput
label="Email"
value={values.email}
onChangeText={handleChange("email")}
onBlur={handleBlur("email")}
error={!!(errors.email && touched.email)} // ✅ add
/>
<TextInput
label="Password"
secureTextEntry
value={values.password}
onChangeText={handleChange("password")}
onBlur={handleBlur("password")}
error={!!(errors.password && touched.password)} // ✅ add
/>
Show error messages
HelperText from React Native Paper displays helpful messages below inputs, like validation errors or hints.
It only shows when the visible prop is true.
<TextInput
label="Email"
value={values.email}
onChangeText={handleChange("email")}
onBlur={handleBlur("email")}
error={!!(errors.email && touched.email)}
/>
{/* add */}
<HelperText
type="error"
visible={!!(errors.email && touched.email)}
>
{errors.email}
</HelperText>
<TextInput
label="Password"
secureTextEntry
value={values.password}
onChangeText={handleChange("password")}
onBlur={handleBlur("password")}
error={!!(errors.password && touched.password)}
/>
{/* add */}
<HelperText
type="error"
visible={!!(errors.password && touched.password)}
>
{errors.password}
</HelperText>
✅ Full Code
import { Formik } from "formik"
import * as Yup from "yup"
import { View } from "react-native"
import { TextInput, Button, HelperText } from "react-native-paper"
const SignupSchema = Yup.object().shape({
email: Yup.string()
.email("Invalid email.")
.required("Required"),
password: Yup.string()
.min(6, "Too Short")
.max(30, "Too Long")
.matches(
/^(?=.*[A-Za-z])(?=.*\d).+$/,
"Password must contain at least one letter and one number"
)
.required("Required")
})
export default function MyForm() {
return (
<Formik
initialValues={{ email: "", password: "" }}
validationSchema={SignupSchema}
onSubmit={values => console.log(values)}
>
{({
handleChange,
handleBlur,
handleSubmit,
values,
errors,
touched
}) => (
<View style={{ padding: 20 }}>
{/* Email */}
<TextInput
label="Email"
value={values.email}
onChangeText={handleChange("email")}
onBlur={handleBlur("email")}
error={!!(errors.email && touched.email)}
/>
<HelperText
type="error"
visible={!!(errors.email && touched.email)}
>
{errors.email}
</HelperText>
{/* Password */}
<TextInput
label="Password"
secureTextEntry
value={values.password}
onChangeText={handleChange("password")}
onBlur={handleBlur("password")}
error={!!(errors.password && touched.password)}
/>
<HelperText
type="error"
visible={!!(errors.password && touched.password)}
>
{errors.password}
</HelperText>
{/* Submit Button */}
<Button mode="contained" onPress={handleSubmit}>
Login / Register
</Button>
</View>
)}
</Formik>
)
}
🎯 Conclusion
-
✅ Formik simplifies form state management
-
✅ Yup provides a powerful validation system
-
✅ With just a few props, you can build clean, user-friendly forms
You’re now ready to create complex forms with ease! 🧠✨