Paramclasses Academy - Blog

Tutorials Details

←
Post 18 of 39
→

How to Create Login and Registration Forms in React Native ?

How to Create Login and Registration Forms in React Native ?

November 5, 2026

1. Introduction

Login and Registration forms are essential parts of most mobile applications. A Login form allows existing users to access their accounts, while a Registration form allows new users to create an account.

In this tutorial, we will build a simple authentication interface using React Native, Expo, and React Navigation.

By the end of this tutorial, you will understand how to:

  • Create Login and Registration screens.

  • Use TextInput to collect user information.

  • Manage form values using useState.

  • Hide passwords using secureTextEntry.

  • Validate email and password fields.

  • Check password confirmation.

  • Navigate between Login and Registration screens.

  • Display success and error messages.

Important: This project demonstrates frontend form handling. It does not create real accounts or authenticate users. Real authentication requires a secure backend or authentication provider.

2. Project Requirements

Before starting, make sure you have:

  • Node.js and npm installed.

  • Visual Studio Code installed.

  • Android Studio Emulator or Expo Go.

  • Basic knowledge of JavaScript and React Native.

  • Basic understanding of React Navigation.

3. Create a New React Native Project

Open your terminal and execute:

npx create-expo-app@latest StudentAuthApp --template blank

Move into the project folder:

cd StudentAuthApp

Open the project in Visual Studio Code:

code .

4. Install React Navigation

We will use Stack Navigation to move between Login and Registration screens.

Install the required packages:

npm install @react-navigation/native @react-navigation/native-stack

Install the Expo-compatible native dependencies:

npx expo install react-native-screens react-native-safe-area-context

Our navigation structure will look like this:

StudentAuthApp
│
├── App.js
├── package.json
└── node_modules/

5. Understand the Login and Registration Flow

The application will contain two screens:

Login Screen

  • Email address input.

  • Password input.

  • Login button.

  • Link to Registration screen.

Registration Screen

  • Full name input.

  • Email address input.

  • Password input.

  • Confirm password input.

  • Create Account button.

  • Link back to Login screen.

The navigation flow will be:

        App
         |
    Stack Navigator
         |
    Login Screen
         |
   Create Account
         |
 Registration Screen
         |
      Login

6. Create the Login and Registration Application

Open App.js and replace its existing content with the following complete code:

import React, { useState } from 'react';

import {
  View,
  Text,
  TextInput,
  Pressable,
  StyleSheet,
  ScrollView,
  KeyboardAvoidingView,
  Platform,
  Alert,
} from 'react-native';

import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

const Stack = createNativeStackNavigator();

// ---------------- LOGIN SCREEN ----------------

function LoginScreen({ navigation }) {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');

  const handleLogin = () => {
    const cleanEmail = email.trim();

    if (!cleanEmail || !password) {
      Alert.alert('Error', 'Please enter your email and password.');
      return;
    }

    const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

    if (!emailPattern.test(cleanEmail)) {
      Alert.alert('Invalid Email', 'Please enter a valid email address.');
      return;
    }

    if (password.length < 6) {
      Alert.alert(
        'Invalid Password',
        'Password must contain at least 6 characters.'
      );
      return;
    }

    Alert.alert(
      'Login Successful',
      'Frontend validation completed successfully. Connect an authentication service for real login.'
    );
  };

  return (
    <KeyboardAvoidingView
      style={styles.screen}
      behavior={Platform.OS === 'ios' ? 'padding' : undefined}
    >
      <ScrollView
        contentContainerStyle={styles.container}
        keyboardShouldPersistTaps="handled"
      >
        <Text style={styles.logo}>STUDENT APP</Text>

        <Text style={styles.title}>Welcome Back!</Text>

        <Text style={styles.subtitle}>
          Login to continue your learning journey.
        </Text>

        <Text style={styles.label}>Email Address</Text>

        <TextInput
          style={styles.input}
          placeholder="Enter your email"
          value={email}
          onChangeText={setEmail}
          keyboardType="email-address"
          autoCapitalize="none"
          autoComplete="email"
        />

        <Text style={styles.label}>Password</Text>

        <TextInput
          style={styles.input}
          placeholder="Enter your password"
          value={password}
          onChangeText={setPassword}
          secureTextEntry={true}
          autoCapitalize="none"
          autoComplete="current-password"
        />

        <Pressable
          style={styles.button}
          onPress={handleLogin}
        >
          <Text style={styles.buttonText}>LOGIN</Text>
        </Pressable>

        <View style={styles.footer}>
          <Text style={styles.footerText}>
            Don't have an account?
          </Text>

          <Pressable
            onPress={() => navigation.navigate('Register')}
          >
            <Text style={styles.link}> Create Account</Text>
          </Pressable>
        </View>
      </ScrollView>
    </KeyboardAvoidingView>
  );
}

// ---------------- REGISTRATION SCREEN ----------------

function RegisterScreen({ navigation }) {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [confirmPassword, setConfirmPassword] = useState('');

  const handleRegister = () => {
    const cleanName = name.trim();
    const cleanEmail = email.trim();

    if (!cleanName || !cleanEmail || !password || !confirmPassword) {
      Alert.alert('Error', 'Please fill in all fields.');
      return;
    }

    const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

    if (!emailPattern.test(cleanEmail)) {
      Alert.alert('Invalid Email', 'Please enter a valid email address.');
      return;
    }

    if (password.length < 6) {
      Alert.alert(
        'Weak Password',
        'Password must contain at least 6 characters.'
      );
      return;
    }

    if (password !== confirmPassword) {
      Alert.alert(
        'Password Mismatch',
        'Password and Confirm Password must be the same.'
      );
      return;
    }

    Alert.alert(
      'Registration Successful',
      'Frontend validation completed. Connect a backend to create a real account.',
      [
        {
          text: 'Continue to Login',
          onPress: () => navigation.navigate('Login'),
        },
      ]
    );
  };

  return (
    <KeyboardAvoidingView
      style={styles.screen}
      behavior={Platform.OS === 'ios' ? 'padding' : undefined}
    >
      <ScrollView
        contentContainerStyle={styles.container}
        keyboardShouldPersistTaps="handled"
      >
        <Text style={styles.logo}>STUDENT APP</Text>

        <Text style={styles.title}>Create Account</Text>

        <Text style={styles.subtitle}>
          Register to get started.
        </Text>

        <Text style={styles.label}>Full Name</Text>

        <TextInput
          style={styles.input}
          placeholder="Enter your full name"
          value={name}
          onChangeText={setName}
          autoCapitalize="words"
          autoComplete="name"
        />

        <Text style={styles.label}>Email Address</Text>

        <TextInput
          style={styles.input}
          placeholder="Enter your email"
          value={email}
          onChangeText={setEmail}
          keyboardType="email-address"
          autoCapitalize="none"
          autoComplete="email"
        />

        <Text style={styles.label}>Password</Text>

        <TextInput
          style={styles.input}
          placeholder="Create a password"
          value={password}
          onChangeText={setPassword}
          secureTextEntry={true}
          autoCapitalize="none"
          autoComplete="new-password"
        />

        <Text style={styles.label}>Confirm Password</Text>

        <TextInput
          style={styles.input}
          placeholder="Confirm your password"
          value={confirmPassword}
          onChangeText={setConfirmPassword}
          secureTextEntry={true}
          autoCapitalize="none"
          autoComplete="new-password"
        />

        <Pressable
          style={styles.button}
          onPress={handleRegister}
        >
          <Text style={styles.buttonText}>CREATE ACCOUNT</Text>
        </Pressable>

        <View style={styles.footer}>
          <Text style={styles.footerText}>
            Already have an account?
          </Text>

          <Pressable
            onPress={() => navigation.navigate('Login')}
          >
            <Text style={styles.link}> Login</Text>
          </Pressable>
        </View>
      </ScrollView>
    </KeyboardAvoidingView>
  );
}

// ---------------- STYLES ----------------

const styles = StyleSheet.create({
  screen: {
    flex: 1,
    backgroundColor: '#F3F6FC',
  },

  container: {
    flexGrow: 1,
    justifyContent: 'center',
    padding: 24,
  },

  logo: {
    fontSize: 18,
    fontWeight: 'bold',
    color: '#2563EB',
    textAlign: 'center',
    marginBottom: 30,
    letterSpacing: 2,
  },

  title: {
    fontSize: 28,
    fontWeight: 'bold',
    color: '#172554',
    textAlign: 'center',
    marginBottom: 8,
  },

  subtitle: {
    fontSize: 14,
    color: '#64748B',
    textAlign: 'center',
    marginBottom: 30,
  },

  label: {
    fontSize: 14,
    fontWeight: '600',
    color: '#334155',
    marginBottom: 8,
    marginTop: 14,
  },

  input: {
    height: 52,
    backgroundColor: '#FFFFFF',
    borderWidth: 1,
    borderColor: '#CBD5E1',
    borderRadius: 10,
    paddingHorizontal: 14,
    fontSize: 15,
  },

  button: {
    backgroundColor: '#2563EB',
    padding: 16,
    borderRadius: 10,
    alignItems: 'center',
    marginTop: 28,
  },

  buttonText: {
    color: '#FFFFFF',
    fontSize: 16,
    fontWeight: 'bold',
  },

  footer: {
    flexDirection: 'row',
    justifyContent: 'center',
    marginTop: 24,
  },

  footerText: {
    color: '#64748B',
    fontSize: 14,
  },

  link: {
    color: '#2563EB',
    fontWeight: 'bold',
    fontSize: 14,
  },
});

// ---------------- MAIN APP ----------------

export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator
        initialRouteName="Login"
        screenOptions={{
          headerShown: false,
        }}
      >
        <Stack.Screen
          name="Login"
          component={LoginScreen}
        />

        <Stack.Screen
          name="Register"
          component={RegisterScreen}
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

7. Understand the Important Code

A. useState for Form Data

We use useState to store the values entered by the user.

const [email, setEmail] = useState('');
const [password, setPassword] = useState('');

Here:

  • email stores the entered email.

  • setEmail updates the email.

  • password stores the entered password.

  • setPassword updates the password.

Whenever the user types something, the state gets updated.

B. TextInput Component

TextInput allows users to enter information.

<TextInput
  placeholder="Enter your email"
  value={email}
  onChangeText={setEmail}
/>

Important properties:

  • placeholder: Displays a hint.

  • value: Displays the current state value.

  • onChangeText: Updates the state.

  • keyboardType: Selects the keyboard type.

  • secureTextEntry: Hides password characters.

  • autoCapitalize: Controls automatic capitalization.

C. Password Security Display

<TextInput
  secureTextEntry={true}
  placeholder="Enter your password"
/>

The secureTextEntry property hides the password while typing.

Remember: hiding a password on screen is not the same as securely storing or transmitting it.

D. Email Validation

const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

if (!emailPattern.test(email)) {
  Alert.alert('Invalid Email', 'Please enter a valid email.');
  return;
}

This checks whether the entered value follows a basic email format.

For production applications, perform validation on the server as well.

E. Password Confirmation

if (password !== confirmPassword) {
  Alert.alert('Password Mismatch', 'Passwords do not match.');
  return;
}

This ensures that both password fields contain the same value.

F. Navigation Between Screens

Open the Registration screen:

navigation.navigate('Register');

Return to the Login screen:

navigation.navigate('Login');

React Navigation uses the registered screen names to identify the destination.

G. Pressable Component

<Pressable onPress={handleLogin}>
  <Text>LOGIN</Text>
</Pressable>

Pressable makes a component respond to touch interactions. Here, pressing the Login button executes handleLogin.

8. Run the Application

Start the Expo development server:

npx expo start

Then:

  1. Open Expo Go on your Android phone and scan the QR code, or start your Android emulator.

  2. Wait for the application to load.

  3. The Login screen should appear.

  4. Select Create Account to open Registration.

  5. Enter registration details and test the validation.

  6. Return to Login and test the email and password validation.

9. Practical Testing

Test the following cases:

Login Screen

  • Submit empty fields.

  • Enter an invalid email.

  • Enter a password shorter than six characters.

  • Enter valid-looking details.

Registration Screen

  • Submit the form without entering details.

  • Enter an invalid email.

  • Enter a short password.

  • Enter different passwords in the two password fields.

  • Enter matching passwords.

Expected result: invalid inputs should show appropriate error messages. Valid-looking inputs should show the demo success message.

10. Common Errors and Solutions

Error 1: Cannot find module @react-navigation/native

Install the navigation package:

npm install @react-navigation/native @react-navigation/native-stack

Error 2: Native dependencies are missing

Run:

npx expo install react-native-screens react-native-safe-area-context

Error 3: Screen does not open

Check that the screen name in navigation.navigate() exactly matches the name registered in Stack.Screen.

Error 4: Password is visible

Make sure the password input contains:

secureTextEntry={true}

Error 5: Keyboard covers the form

Use KeyboardAvoidingView and ScrollView so the form can adjust and scroll when the keyboard appears.

11. Best Practices

  • Use clear labels and placeholders.

  • Validate all required fields.

  • Keep passwords hidden while typing.

  • Do not store plain-text passwords.

  • Never hardcode real user credentials in the application.

  • Use HTTPS when communicating with a backend.

  • Perform authentication and authorization on a secure server.

  • Show helpful error messages.

  • Avoid logging passwords or other sensitive information.

  • Use a trusted authentication service or a properly secured backend for real applications.

12. Conclusion

In this tutorial, we created Login and Registration screens using React Native.

We learned how to use TextInput, useState, Pressable, Alert, and React Navigation. We also implemented basic email validation, password length validation, and password confirmation.

The project demonstrates the frontend authentication flow. To make it a real authentication system, we will need to connect it to a backend or an authentication provider.

13. Frequently Asked Questions

Q1. What is a Login form in React Native?

A Login form collects user credentials, such as an email address and password, to request access to an account.

Q2. Which component is used to enter user information?

The TextInput component is used to collect text input from users.

Q3. How can we hide a password?

Use the secureTextEntry property in TextInput.

Q4. What is the purpose of useState?

useState stores and updates changing form values such as name, email, and password.

Q5. How do we move from Login to Registration?

Use React Navigation:

navigation.navigate('Register');

Q6. Does this tutorial create real user accounts?

No. It demonstrates frontend validation and navigation. Real account creation requires a backend or authentication provider.

Q7. Can we connect a React Native Login form to PHP and MySQL?

Yes. A React Native application can send requests to a PHP API, which can validate credentials and communicate with a MySQL database. Passwords must be securely hashed on the server.

Q8. Can Firebase be used for Login and Registration?

Yes. Firebase Authentication supports email and password authentication, among other sign-in methods.

←
Post 18 of 39
→