Lesson 149 of 158 – Project Login Screen
94%

Project Login Screen

In this lesson, we will create the Login Screen for our Student Management mobile application using React Native, TypeScript, Axios, and the PHP REST API created in the previous lessons.

The login screen will collect the user's email and password, send them to the PHP login API, receive the JWT token, and store the authentication information for later protected API requests.

Project Goal: Build a complete React Native login screen that communicates with the PHP/MySQL REST API using Axios, TypeScript, and JWT authentication.

1. Login Screen Flow

Login Screen
      ↓
Enter Email
      ↓
Enter Password
      ↓
Press Login
      ↓
Axios POST Request
      ↓
PHP Login API
      ↓
Validate User
      ↓
password_verify()
      ↓
Generate JWT
      ↓
Return Token
      ↓
Store Token
      ↓
Open App Screen

2. Login Screen Components

A basic login screen needs the following components:

  • Email input.
  • Password input.
  • Login button.
  • Loading indicator.
  • Error message.
  • Optional registration link.

3. Login API Endpoint

The mobile application sends the login information to the PHP login endpoint.

POST /api/login.php

The email and password are sent in the JSON request body.

4. Login Request Data

{
    "email": "rahul@example.com",
    "password": "123456"
}

The password is sent over HTTPS to the server. The server verifies the password against the stored password hash.

5. TypeScript Login Request

interface LoginRequest {
    email: string;
    password: string;
}

This interface defines the data that the mobile application sends to the login API.

6. Login Response Interface

interface User {
    id: number;
    name: string;
    email: string;
    role: string;
}

interface LoginResponse {
    success: boolean;
    message: string;
    token: string;
    user: User;
}

The interface represents a successful login response.

7. Import React Native Components

import React, {
    useState
} from "react";

import {
    View,
    Text,
    TextInput,
    Button,
    StyleSheet,
    Alert,
    ActivityIndicator
} from "react-native";

8. Login State

const [email, setEmail] =
    useState("");

const [password, setPassword] =
    useState("");

const [loading, setLoading] =
    useState(false);

const [error, setError] =
    useState("");

These states store the form values and the current API request state.

9. Email Input

<TextInput
    placeholder="Email"
    value={email}
    onChangeText={setEmail}
    keyboardType="email-address"
    autoCapitalize="none"
/>

autoCapitalize="none" is useful for email input because email addresses normally should not be automatically capitalized.

10. Password Input

<TextInput
    placeholder="Password"
    value={password}
    onChangeText={setPassword}
    secureTextEntry
    autoCapitalize="none"
/>

The secureTextEntry property hides the password while the user is typing.

11. Validate Login Form

if (!email.trim()) {

    setError(
        "Email is required"
    );

    return;
}

if (!password) {

    setError(
        "Password is required"
    );

    return;
}

Client-side validation improves the user experience, but server-side validation is still required.

12. Validate Email Format

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

if (
    !emailPattern.test(
        email.trim()
    )
) {

    setError(
        "Enter a valid email address"
    );

    return;
}

13. Create Login Function

const handleLogin =
    async () => {

    setError("");

    // validation
    // API request
    // token storage
    // navigation

};

The login function controls the complete login process.

14. Send Login Request with Axios

const response =
    await api.post<LoginResponse>(
        "/login.php",
        {
            email: email.trim(),
            password: password
        }
    );

The Axios instance sends the email and password to the PHP login endpoint.

15. Login API Server Flow

POST /login.php
       ↓
Read JSON
       ↓
Validate Email
       ↓
Validate Password
       ↓
Find User
       ↓
password_verify()
       ↓
Create JWT
       ↓
Return JSON

The PHP API performs the actual authentication.

16. Password Verification

The database should contain a password hash rather than a plain text password.

if (
    !password_verify(
        $password,
        $user['password']
    )
) {

    http_response_code(401);

    echo json_encode([
        "success" => false,
        "message" =>
            "Invalid email or password"
    ]);

    exit;
}

17. JWT Login Response

After successful password verification, the PHP API creates a JWT and returns it to the mobile application.

{
    "success": true,
    "message": "Login successful",
    "token": "YOUR_JWT_TOKEN",
    "user": {
        "id": 5,
        "name": "Rahul Kumar",
        "email": "rahul@example.com",
        "role": "student"
    }
}

18. Store JWT Token

The application needs the token for later protected API requests. AsyncStorage can be used for token persistence in this project.

import AsyncStorage
    from "@react-native-async-storage/async-storage";

await AsyncStorage.setItem(
    "auth_token",
    response.data.token
);

19. Store User Information

await AsyncStorage.setItem(
    "auth_user",
    JSON.stringify(
        response.data.user
    )
);

Objects must be converted into strings before storing them in AsyncStorage.

20. Complete Login Function

const handleLogin =
    async () => {

    setError("");

    if (!email.trim()) {

        setError(
            "Email is required"
        );

        return;
    }

    if (!password) {

        setError(
            "Password is required"
        );

        return;
    }

    try {

        setLoading(true);

        const response =
            await api.post<LoginResponse>(
                "/login.php",
                {
                    email:
                        email.trim(),
                    password
                }
            );

        if (
            response.data.success
        ) {

            await AsyncStorage.setItem(
                "auth_token",
                response.data.token
            );

            await AsyncStorage.setItem(
                "auth_user",
                JSON.stringify(
                    response.data.user
                )
            );

            Alert.alert(
                "Success",
                "Login successful"
            );

            // Navigate to
            // application screen

        }

    } catch (error) {

        setError(
            "Invalid email or password"
        );

    } finally {

        setLoading(false);

    }
};

21. Login Button

<Button
    title={
        loading
        ? "Logging in..."
        : "Login"
    }
    onPress={handleLogin}
/>

The button starts the login process.

22. Show Loading Indicator

{loading && (
    <ActivityIndicator />
)}

A loading indicator tells the user that the login request is being processed.

23. Display Login Error

{error !== "" && (
    <Text>
        {error}
    </Text>
)}

The application can display a friendly error message when the login fails.

24. Handle HTTP Status Codes

catch (error) {

    if (
        axios.isAxiosError(error) &&
        error.response
    ) {

        if (
            error.response.status === 401
        ) {

            setError(
                "Invalid email or password"
            );

        } else if (
            error.response.status === 422
        ) {

            setError(
                "Please check your input"
            );

        } else {

            setError(
                "Unable to login"
            );
        }

    } else {

        setError(
            "Network error"
        );
    }
}

25. Complete Login Screen UI

return (
    <View>

        <Text>
            Student Management
        </Text>

        <Text>
            Login
        </Text>

        <TextInput
            placeholder="Email"
            value={email}
            onChangeText={setEmail}
            keyboardType="email-address"
            autoCapitalize="none"
        />

        <TextInput
            placeholder="Password"
            value={password}
            onChangeText={setPassword}
            secureTextEntry
            autoCapitalize="none"
        />

        {error !== "" && (
            <Text>
                {error}
            </Text>
        )}

        {loading && (
            <ActivityIndicator />
        )}

        <Button
            title={
                loading
                ? "Logging in..."
                : "Login"
            }
            onPress={handleLogin}
        />

    </View>
);

26. Login Screen Navigation

After successful authentication, the application should move from the authentication flow to the main application flow.

Login Screen
     ↓
Successful Login
     ↓
JWT Stored
     ↓
Auth State Updated
     ↓
Main App Navigator
     ↓
Student List / Dashboard

In the next authentication lessons, the login state will be connected to the complete navigation and authentication flow.

27. Login Screen Security

  • Use HTTPS for login requests.
  • Never store plain text passwords.
  • Never return password hashes to the mobile application.
  • Use password_hash() during registration.
  • Use password_verify() during login.
  • Use a strong JWT secret on the server.
  • Do not put JWT tokens in URLs.
  • Do not log passwords or JWT tokens.
  • Return generic invalid-login messages.

28. Testing Login Screen

Step 1: Start the PHP API.

Step 2: Start the React Native application.

Step 3: Open the Login screen.

Step 4: Enter a registered email.

Step 5: Enter the correct password.

Step 6: Press Login.

Expected Result:

Login successful
      ↓
JWT received
      ↓
Token stored
      ↓
User information stored
      ↓
Main application opens

29. Complete Login Architecture

React Native
     |
     | email + password
     ↓
Axios
     |
     | POST /login.php
     ↓
PHP REST API
     |
     ↓
Validate Input
     |
     ↓
MySQL User
     |
     ↓
password_verify()
     |
     ↓
Generate JWT
     |
     ↓
JSON Response
     |
     ↓
React Native
     |
     ↓
AsyncStorage
     |
     ↓
Authentication State
     |
     ↓
Main Application

30. Project Login Screen Summary

The Login Screen connects the React Native application to the authentication API created in the backend.

  • The user enters email and password.
  • TypeScript interfaces define request and response data.
  • Client-side validation checks the form.
  • Axios sends the login request.
  • The PHP API verifies the user.
  • password_verify() checks the password.
  • The PHP API generates a JWT after successful authentication.
  • React Native receives the JWT.
  • AsyncStorage stores the authentication token.
  • The user information can also be stored locally.
  • Authentication state can then control application navigation.
  • The next lesson will create the Registration Screen.

📌 Key Points

  • Login uses a POST request.
  • The request contains email and password.
  • Use TypeScript interfaces for login data.
  • Axios communicates with the PHP REST API.
  • The server uses password_verify().
  • The server returns a JWT after successful authentication.
  • AsyncStorage can persist the JWT in this project.
  • Do not store plain text passwords.
  • Use HTTPS for production authentication requests.
  • Authentication state controls access to the main application.

🧠 Quick Quiz

Question: Which function is used by the PHP login API to verify a user's password against the stored password hash?