In this lesson, we will create the Registration Screen for our Student Management mobile application using React Native, TypeScript, Axios, and the PHP REST API.
The registration screen will allow a new user to enter their name, email, and password. React Native will send the data to the PHP registration API, where the server will validate the data, hash the password, save the user in MySQL, and return a JSON response.
Registration Screen
↓
Enter Name
↓
Enter Email
↓
Enter Password
↓
Confirm Password
↓
Press Register
↓
Axios POST
↓
PHP Registration API
↓
Validate Data
↓
Check Duplicate Email
↓
password_hash()
↓
MySQL INSERT
↓
JSON Response
Our basic registration form can contain:
The React Native application sends the registration data to:
POST /api/register.php
The request body contains JSON data.
{
"name": "Rahul Kumar",
"email": "rahul@example.com",
"password": "123456"
}
The password is sent to the server over HTTPS and is never stored as plain text.
interface RegisterRequest {
name: string;
email: string;
password: string;
}
This interface describes the data sent from React Native to the registration API.
interface RegisterResponse {
success: boolean;
message: string;
user?: {
id: number;
name: string;
email: string;
};
}
The optional user property can be returned after a
successful registration.
import React, {
useState
} from "react";
import {
View,
Text,
TextInput,
Button,
ActivityIndicator
} from "react-native";
const [name, setName] =
useState("");
const [email, setEmail] =
useState("");
const [password, setPassword] =
useState("");
const [confirmPassword,
setConfirmPassword] =
useState("");
const [loading, setLoading] =
useState(false);
const [error, setError] =
useState("");
<TextInput
placeholder="Full Name"
value={name}
onChangeText={setName}
/>
The name input stores the user's full name in React state.
<TextInput
placeholder="Email"
value={email}
onChangeText={setEmail}
keyboardType="email-address"
autoCapitalize="none"
/>
Email addresses should normally be entered without automatic capitalization.
<TextInput
placeholder="Password"
value={password}
onChangeText={setPassword}
secureTextEntry
autoCapitalize="none"
/>
The secureTextEntry property hides the password.
<TextInput
placeholder="Confirm Password"
value={confirmPassword}
onChangeText={
setConfirmPassword
}
secureTextEntry
autoCapitalize="none"
/>
Confirm password allows the user to verify that both password fields contain the same value.
if (!name.trim()) {
setError(
"Name is required"
);
return;
}
if (!email.trim()) {
setError(
"Email is required"
);
return;
}
if (!password) {
setError(
"Password is required"
);
return;
}
const emailPattern =
/^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (
!emailPattern.test(
email.trim()
)
) {
setError(
"Enter a valid email"
);
return;
}
if (password.length < 6) {
setError(
"Password must contain at least 6 characters"
);
return;
}
Client-side validation provides immediate feedback to the user. The server must also perform its own validation.
if (
password !== confirmPassword
) {
setError(
"Passwords do not match"
);
return;
}
Registration should not continue until both password fields match.
const handleRegister =
async () => {
setError("");
// Validate form
// Send API request
// Handle response
};
The registration function controls the complete form submission process.
const response =
await api.post<RegisterResponse>(
"/register.php",
{
name: name.trim(),
email: email.trim(),
password
}
);
Axios converts the JavaScript object into a JSON request according to the configured request headers.
POST /register.php
↓
Read JSON
↓
Validate Name
↓
Validate Email
↓
Validate Password
↓
Check Duplicate Email
↓
password_hash()
↓
PDO INSERT
↓
HTTP 201
↓
JSON Response
The PHP server must never store the password as plain text.
$hashedPassword =
password_hash(
$password,
PASSWORD_DEFAULT
);
The generated hash is stored in the database.
$stmt = $pdo->prepare(
"SELECT id
FROM users
WHERE email = ?"
);
$stmt->execute([$email]);
if ($stmt->fetch()) {
http_response_code(409);
echo json_encode([
"success" => false,
"message" =>
"Email already registered"
]);
exit;
}
HTTP 409 indicates a conflict with an existing resource.
$stmt = $pdo->prepare(
"INSERT INTO users
(name, email, password, role)
VALUES (?, ?, ?, ?)"
);
$stmt->execute([
$name,
$email,
$hashedPassword,
'student'
]);
The password hash is stored instead of the original password.
http_response_code(201);
echo json_encode([
"success" => true,
"message" =>
"Registration successful",
"user" => [
"id" => $pdo->lastInsertId(),
"name" => $name,
"email" => $email
]
]);
HTTP 201 indicates that a new resource was created.
<?php
header(
"Content-Type: application/json"
);
require_once '../config/database.php';
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode([
"success" => false,
"message" => "Method not allowed"
]);
exit;
}
try {
$input = json_decode(
file_get_contents("php://input"),
true
);
$name =
trim($input['name'] ?? '');
$email =
trim($input['email'] ?? '');
$password =
$input['password'] ?? '';
if ($name === '') {
http_response_code(422);
echo json_encode([
"success" => false,
"message" =>
"Name is required"
]);
exit;
}
if (
!filter_var(
$email,
FILTER_VALIDATE_EMAIL
)
) {
http_response_code(422);
echo json_encode([
"success" => false,
"message" =>
"Valid email is required"
]);
exit;
}
if (strlen($password) < 6) {
http_response_code(422);
echo json_encode([
"success" => false,
"message" =>
"Password must contain at least 6 characters"
]);
exit;
}
$stmt = $pdo->prepare(
"SELECT id
FROM users
WHERE email = ?"
);
$stmt->execute([$email]);
if ($stmt->fetch()) {
http_response_code(409);
echo json_encode([
"success" => false,
"message" =>
"Email already registered"
]);
exit;
}
$hashedPassword =
password_hash(
$password,
PASSWORD_DEFAULT
);
$stmt = $pdo->prepare(
"INSERT INTO users
(name, email, password, role)
VALUES (?, ?, ?, ?)"
);
$stmt->execute([
$name,
$email,
$hashedPassword,
'student'
]);
http_response_code(201);
echo json_encode([
"success" => true,
"message" =>
"Registration successful",
"user" => [
"id" =>
$pdo->lastInsertId(),
"name" => $name,
"email" => $email
]
]);
} catch (Exception $e) {
error_log($e->getMessage());
http_response_code(500);
echo json_encode([
"success" => false,
"message" =>
"Unable to register user"
]);
}
if (response.data.success) {
setName("");
setEmail("");
setPassword("");
setConfirmPassword("");
Alert.alert(
"Success",
"Registration successful"
);
// Navigate to Login Screen
}
After successful registration, the user can be redirected to the Login screen.
catch (error) {
if (
axios.isAxiosError(error) &&
error.response
) {
if (
error.response.status === 409
) {
setError(
"Email is already registered"
);
} else if (
error.response.status === 422
) {
setError(
error.response.data.message
);
} else {
setError(
"Registration failed"
);
}
} else {
setError(
"Network error"
);
}
}
{loading && (
<ActivityIndicator />
)}
<Button
title={
loading
? "Registering..."
: "Register"
}
onPress={handleRegister}
/>
The loading state provides feedback while the registration request is being processed.
return (
<View>
<Text>
Student Management
</Text>
<Text>
Create Account
</Text>
<TextInput
placeholder="Full Name"
value={name}
onChangeText={setName}
/>
<TextInput
placeholder="Email"
value={email}
onChangeText={setEmail}
keyboardType="email-address"
autoCapitalize="none"
/>
<TextInput
placeholder="Password"
value={password}
onChangeText={setPassword}
secureTextEntry
autoCapitalize="none"
/>
<TextInput
placeholder="Confirm Password"
value={confirmPassword}
onChangeText={
setConfirmPassword
}
secureTextEntry
autoCapitalize="none"
/>
{error !== "" && (
<Text>
{error}
</Text>
)}
{loading && (
<ActivityIndicator />
)}
<Button
title={
loading
? "Registering..."
: "Register"
}
onPress={handleRegister}
/>
</View>
);
React Native Registration
↓
Name + Email + Password
↓
Client Validation
↓
Axios POST
↓
PHP REST API
↓
Server Validation
↓
Duplicate Email Check
↓
password_hash()
↓
PDO INSERT
↓
MySQL
↓
HTTP 201
↓
Registration Success
↓
Navigate to Login
The Registration Screen allows new users to create accounts in the Student Management application.
password_hash() securely hashes the password.password_hash() to store passwords securely.Question: Which PHP function should be used to securely hash a user's password before storing it in the database?