DEV Community

Ajmal Hasan
Ajmal Hasan

Posted on

Building Forms in React Native with React Hook Form and Yup

Forms are an essential part of any mobile application, and handling them efficiently can enhance user experience and application performance. In this blog, we'll explore the best practices for managing forms in React Native using react-hook-form and Yup for validation.

Why Use React Hook Form?

React Hook Form is a lightweight library that helps manage form states and validation with minimal re-renders. It offers better performance compared to controlled components and integrates seamlessly with Yup, a schema validation library.

Key Benefits:

  • Minimal re-renders.
  • Improved performance.
  • Simple and declarative validation.
  • Integrates well with existing UI components.

Setting Up the Project

To get started, install the necessary dependencies:

yarn add react-hook-form @hookform/resolvers yup
Enter fullscreen mode Exit fullscreen mode

react-hook-form
hookform-resolvers
yup

Defining Validation Schemas with Yup

Using Yup, we define schemas for form validation. Here are a few common scenarios:

1. Login Form Validation

import * as yup from 'yup';

export const loginSchema = yup.object({
  username: yup.string().min(3, 'Username must be at least 3 characters').required('Username is required'),
  password: yup.string().min(5, 'Password must be at least 5 characters').required('Password is required'),
});
Enter fullscreen mode Exit fullscreen mode

2. Forgot Password Validation

export const forgotPasswordSchema = yup.object({
  username: yup.string().required('Username is required'),
});
Enter fullscreen mode Exit fullscreen mode

3. Request Time Off Validation

export const requestTimeOffSchema = yup.object({
  leaveType: yup.object().required('Please select leave type'),
  dateRange: yup.object().required('Please select a date'),
});
Enter fullscreen mode Exit fullscreen mode

4. Bank Letter Validation

export const bankLetterSchema = yup.object({
  leaveType: yup.object().required('Please select letter type'),
  bankName: yup.object().required('Please select a bank'),
  comments: yup
    .string()
    .max(50, 'Comments should not exceed 50 characters')
    .matches(/^[a-zA-Z0-9 .]*$/, 'Comments should not contain special characters except .')
    .nullable(),
});
Enter fullscreen mode Exit fullscreen mode

5. Incident Report Validation

import moment from 'moment';

const timeAndDateOfIncident = {
  dateOfIncident: yup
    .object({ startDate: yup.date().required('Please select date of incident') })
    .required('Please select date of incident'),
  timeOfIncident: yup
    .string()
    .required('Please select time of incident')
    .test('time-validation', 'Time should not exceed current time', function (value) {
      const { startDate } = this.parent.dateOfIncident;
      if (!startDate || !value) return true;
      const currentDate = moment();
      const selectedDate = moment(startDate);
      const selectedTime = moment(value, 'ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
      return !(selectedDate.isSame(currentDate, 'day') && selectedTime.isAfter(currentDate));
    }),
};

export const goodObservation = yup.object({
  incidentLocation: yup.object().required('Please select location'),
  comments: yup.string().required('What you observed is required'),
  ...timeAndDateOfIncident,
});
Enter fullscreen mode Exit fullscreen mode

6. Attendance Validation

export const singleShiftAttendance = yup.object({
  f1: yup
    .string()
    .required('Check-in time is required')
    .test('is-lower-than-f2', 'Check-in time must be less than Check-out time', function (value) {
      const { f2, f1nextDay, f2nextDay } = this.parent;
      if (!value || !f2 || f1nextDay || f2nextDay) return true;
      return new Date(value) < new Date(f2);
    }),
  f2: yup
    .string()
    .required('Check-out time is required')
    .test('is-greater-than-f1', 'Check-out time must be greater than Check-in time', function (value) {
      const { f1, f1nextDay, f2nextDay } = this.parent;
      if (!value || !f1 || f1nextDay || f2nextDay) return true;
      return new Date(value) > new Date(f1);
    }),
  reason: yup.object().required('Please select reason'),
});
Enter fullscreen mode Exit fullscreen mode

Implementing Forms with React Hook Form

Now, let's integrate React Hook Form with our validation schemas.

Example: Login Form Implementation

import React from 'react';
import { View, Text, TextInput, Button } from 'react-native';
import { useForm, Controller } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import { loginSchema } from './validationSchemas';

const LoginForm = () => {
  const {
    control,
    handleSubmit,
    formState: { errors },
  } = useForm({
    resolver: yupResolver(loginSchema),
  });

  const onSubmit = (data) => {
    console.log('Login Data:', data);
  };

  return (
    <View>
      <Text>Username</Text>
      <Controller
        control={control}
        name="username"
        render={({ field: { onChange, value } }) => (
          <TextInput
            style={{ borderWidth: 1, padding: 10 }}
            onChangeText={onChange}
            value={value}
          />
        )}
      />
      {errors.username && <Text style={{ color: 'red' }}>{errors.username.message}</Text>}

      <Text>Password</Text>
      <Controller
        control={control}
        name="password"
        render={({ field: { onChange, value } }) => (
          <TextInput
            style={{ borderWidth: 1, padding: 10 }}
            secureTextEntry
            onChangeText={onChange}
            value={value}
          />
        )}
      />
      {errors.password && <Text style={{ color: 'red' }}>{errors.password.message}</Text>}

      <Button title="Login" onPress={handleSubmit(onSubmit)} />
    </View>
  );
};

export default LLoginForm
Enter fullscreen mode Exit fullscreen mode

Conclusion

Using React Hook Form and Yup together simplifies form handling in React Native. It ensures better performance, maintainability, and user experience. By following best practices, you can create scalable and efficient forms for your mobile applications.

Stay tuned for more tips on building robust React Native apps!

Top comments (0)