In this lesson, we will create the Edit Student screen for our Student Management mobile application using React Native, TypeScript, Axios, and the PHP REST API.
The Edit Student screen will receive a student ID, load the existing student information, allow the user to modify the data, and send the updated information to the PHP API using the HTTP PUT method.
Student List
↓
Select Edit
↓
Pass Student ID
↓
Edit Student Screen
↓
GET Existing Student
↓
Display Existing Data
↓
Modify Data
↓
Client Validation
↓
PUT Request
↓
JWT Authentication
↓
PHP REST API
↓
MySQL UPDATE
↓
Success Response
↓
Student List
The HTTP PUT method is commonly used when updating an
existing resource.
PUT /api/students.php?id=5
Here, 5 identifies the student that needs to be updated.
interface Student {
id: number;
name: string;
email: string;
mobile: string;
course: string;
address: string;
}
interface UpdateStudentRequest {
name: string;
email: string;
mobile: string;
course: string;
address: string;
}
The ID is normally supplied through the URL while the updated fields are sent in the JSON request body.
interface UpdateStudentResponse {
success: boolean;
message: string;
data?: Student;
}
import React, {
useEffect,
useState
} from "react";
import {
View,
Text,
TextInput,
TouchableOpacity,
ScrollView,
ActivityIndicator
} from "react-native";
React Navigation can pass the student ID from the Student List or Student Details screen.
const { id } = route.params;
For example:
{
id: 5
}
const [name, setName] =
useState("");
const [email, setEmail] =
useState("");
const [mobile, setMobile] =
useState("");
const [course, setCourse] =
useState("");
const [address, setAddress] =
useState("");
const [loading, setLoading] =
useState(true);
const [saving, setSaving] =
useState(false);
const [error, setError] =
useState("");
const [success, setSuccess] =
useState("");
const loadStudent =
async () => {
try {
setLoading(true);
setError("");
const response =
await api.get<StudentProfileResponse>(
"/student_profile.php",
{
params: {
id
}
}
);
const student =
response.data.data;
setName(student.name);
setEmail(student.email);
setMobile(student.mobile);
setCourse(student.course);
setAddress(student.address);
} catch (error) {
setError(
"Unable to load student."
);
} finally {
setLoading(false);
}
};
useEffect(() => {
loadStudent();
}, [id]);
When the screen opens, the existing student information is loaded into the form fields.
<TextInput
placeholder="Student name"
value={name}
onChangeText={setName}
/>
Because the field is controlled, the current student name remains available in React state.
<TextInput
placeholder="Email"
value={email}
onChangeText={setEmail}
keyboardType="email-address"
autoCapitalize="none"
/>
<TextInput
placeholder="Mobile"
value={mobile}
onChangeText={setMobile}
keyboardType="phone-pad"
/>
<TextInput
placeholder="Course"
value={course}
onChangeText={setCourse}
/>
<TextInput
placeholder="Address"
value={address}
onChangeText={setAddress}
multiline
/>
if (
!name ||
!email ||
!mobile ||
!course
) {
setError(
"Please fill all required fields."
);
return;
}
Client-side validation gives immediate feedback to the user.
const emailPattern =
/^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailPattern.test(email)) {
setError(
"Enter a valid email address."
);
return;
}
const studentData:
UpdateStudentRequest = {
name: name.trim(),
email: email.trim(),
mobile: mobile.trim(),
course: course.trim(),
address: address.trim()
};
const response =
await api.put<UpdateStudentResponse>(
`/students.php?id=${id}`,
studentData
);
The student ID identifies the record while the JSON body contains the updated values.
The update API should be protected with JWT authentication.
Authorization:
Bearer YOUR_JWT_TOKEN
If the Axios instance contains a request interceptor, the token can be added automatically.
$id = filter_input(
INPUT_GET,
'id',
FILTER_VALIDATE_INT
);
if (!$id) {
http_response_code(400);
echo json_encode([
"success" => false,
"message" => "Invalid student ID"
]);
exit;
}
$input = json_decode(
file_get_contents("php://input"),
true
);
$name =
trim($input['name'] ?? '');
$email =
trim($input['email'] ?? '');
$mobile =
trim($input['mobile'] ?? '');
$course =
trim($input['course'] ?? '');
$address =
trim($input['address'] ?? '');
if (
$name === '' ||
$email === '' ||
$mobile === '' ||
$course === ''
) {
http_response_code(422);
echo json_encode([
"success" => false,
"message" =>
"Required fields are missing."
]);
exit;
}
Server-side validation must always be performed because mobile application validation can be bypassed.
$stmt = $pdo->prepare(
"UPDATE students
SET
name = ?,
email = ?,
mobile = ?,
course = ?,
address = ?
WHERE id = ?"
);
$stmt->execute([
$name,
$email,
$mobile,
$course,
$address,
$id
]);
$updated = $stmt->rowCount();
The prepared statement safely updates the selected student.
$check = $pdo->prepare(
"SELECT id
FROM students
WHERE id = ?"
);
$check->execute([$id]);
if (!$check->fetch()) {
http_response_code(404);
echo json_encode([
"success" => false,
"message" =>
"Student not found."
]);
exit;
}
http_response_code(200);
echo json_encode([
"success" => true,
"message" =>
"Student updated successfully.",
"data" => [
"id" => $id,
"name" => $name,
"email" => $email,
"mobile" => $mobile,
"course" => $course,
"address" => $address
]
]);
HTTP 200 indicates that the update request was successfully processed.
catch (error) {
if (
axios.isAxiosError(error)
) {
if (
error.response?.status === 401
) {
setError(
"Session expired."
);
} else if (
error.response?.status === 404
) {
setError(
"Student not found."
);
} else if (
error.response?.status === 422
) {
setError(
error.response.data.message
|| "Invalid data."
);
} else {
setError(
"Unable to update student."
);
}
} else {
setError(
"Network error."
);
}
}
const updateStudent =
async () => {
try {
setError("");
setSuccess("");
if (
!name ||
!email ||
!mobile ||
!course
) {
setError(
"Please fill all required fields."
);
return;
}
const studentData:
UpdateStudentRequest = {
name: name.trim(),
email: email.trim(),
mobile: mobile.trim(),
course: course.trim(),
address: address.trim()
};
setSaving(true);
const response =
await api.put<UpdateStudentResponse>(
`/students.php?id=${id}`,
studentData
);
setSuccess(
response.data.message
);
} catch (error) {
if (
axios.isAxiosError(error)
) {
setError(
error.response?.data?.message
|| "Unable to update student."
);
} else {
setError(
"Network error."
);
}
} finally {
setSaving(false);
}
};
const EditStudentScreen =
({ route }: any) => {
const { id } = route.params;
const [name, setName] =
useState("");
const [email, setEmail] =
useState("");
const [mobile, setMobile] =
useState("");
const [course, setCourse] =
useState("");
const [address, setAddress] =
useState("");
const [loading, setLoading] =
useState(true);
const [saving, setSaving] =
useState(false);
const [error, setError] =
useState("");
const loadStudent =
async () => {
try {
const response =
await api.get<StudentProfileResponse>(
"/student_profile.php",
{
params: {
id
}
}
);
const student =
response.data.data;
setName(student.name);
setEmail(student.email);
setMobile(student.mobile);
setCourse(student.course);
setAddress(student.address);
} catch (error) {
setError(
"Unable to load student."
);
} finally {
setLoading(false);
}
};
const updateStudent =
async () => {
if (
!name ||
!email ||
!mobile ||
!course
) {
setError(
"Please fill all required fields."
);
return;
}
try {
setSaving(true);
setError("");
await api.put(
`/students.php?id=${id}`,
{
name: name.trim(),
email: email.trim(),
mobile: mobile.trim(),
course: course.trim(),
address: address.trim()
}
);
} catch (error) {
setError(
"Unable to update student."
);
} finally {
setSaving(false);
}
};
useEffect(() => {
loadStudent();
}, [id]);
if (loading) {
return (
<ActivityIndicator
size="large"
/>
);
}
return (
<ScrollView>
<Text>
Edit Student
</Text>
<TextInput
placeholder="Name"
value={name}
onChangeText={setName}
/>
<TextInput
placeholder="Email"
value={email}
onChangeText={setEmail}
/>
<TextInput
placeholder="Mobile"
value={mobile}
onChangeText={setMobile}
/>
<TextInput
placeholder="Course"
value={course}
onChangeText={setCourse}
/>
<TextInput
placeholder="Address"
value={address}
onChangeText={setAddress}
multiline
/>
{error !== "" && (
<Text>
{error}
</Text>
)}
<TouchableOpacity
onPress={updateStudent}
>
<Text>
{saving
? "Updating..."
: "Update Student"}
</Text>
</TouchableOpacity>
</ScrollView>
);
};
The Edit Student screen can be opened from the Student List or Student Details screen.
navigation.navigate(
"EditStudent",
{
id: student.id
}
);
After a successful update, the application can return to the Student Details or Student List screen.
Student List / Details
↓
Edit Student
↓
Student ID
↓
GET Existing Student
↓
Fill Form
↓
Modify Data
↓
Client Validation
↓
PUT /students.php?id=5
↓
JWT Verification
↓
Server Validation
↓
PDO UPDATE
↓
HTTP 200
↓
Updated Student
↓
Student List / Details
The Edit Student screen allows authenticated users to modify an existing student record through the REST API.
Question: Which HTTP method is used in our project to update an existing student?