Axios is commonly used in React Native applications to communicate with REST APIs. When Axios is combined with TypeScript, we can type request data, response data, errors, and reusable API functions.
Axios is a JavaScript library used to make HTTP requests to APIs.
import axios from "axios";
It can be used with GET, POST, PUT, PATCH, and DELETE requests.
Install Axios in the React Native project:
npm install axios
After installation, Axios can be imported into TypeScript files.
import axios from "axios";
We can now use Axios to communicate with the PHP REST API.
const api = axios.create({
baseURL: "https://example.com/api"
});
export default api;
A reusable Axios instance keeps API configuration in one place.
interface Student {
id: number;
name: string;
email: string;
mobile: string;
}
This interface describes one student returned by the API.
interface StudentResponse {
success: boolean;
message: string;
data: Student[];
}
This interface describes a response containing multiple students.
const response =
await api.get<StudentResponse>(
"/students"
);
The generic type tells TypeScript what structure to expect from the response.
const response =
await api.get<StudentResponse>(
"/students"
);
const students = response.data.data;
console.log(students);
TypeScript understands that students is a
Student[].
interface CreateStudentRequest {
name: string;
email: string;
mobile: string;
}
const studentData: CreateStudentRequest = {
name: "Rahul",
email: "rahul@example.com",
mobile: "9876543210"
};
await api.post(
"/students",
studentData
);
interface CreateStudentResponse {
success: boolean;
message: string;
data: Student;
}
const response =
await api.post<CreateStudentResponse>(
"/students",
studentData
);
console.log(response.data.data);
interface UpdateStudentRequest {
name: string;
email: string;
mobile: string;
}
const data: UpdateStudentRequest = {
name: "Rahul Kumar",
email: "rahul@example.com",
mobile: "9876543210"
};
const response =
await api.put(
"/students/10",
data
);
interface DeleteResponse {
success: boolean;
message: string;
}
const response =
await api.delete<DeleteResponse>(
"/students/10"
);
console.log(response.data.message);
interface StudentQuery {
search?: string;
page?: number;
limit?: number;
}
const params: StudentQuery = {
search: "Rahul",
page: 1,
limit: 10
};
const response =
await api.get<StudentResponse>(
"/students",
{
params
}
);
interface SortParams {
sort: string;
order: "asc" | "desc";
}
const params: SortParams = {
sort: "name",
order: "asc"
};
const response =
await api.get<StudentResponse>(
"/students",
{
params
}
);
interface PaginationMeta {
page: number;
limit: number;
total: number;
totalPages: number;
}
interface StudentListResponse {
success: boolean;
message: string;
data: Student[];
meta: PaginationMeta;
}
Pagination metadata can also be strongly typed.
const [students, setStudents] =
useState<Student[]>([]);
const loadStudents = async () => {
const response =
await api.get<StudentResponse>(
"/students"
);
setStudents(response.data.data);
};
const [loading, setLoading] =
useState<boolean>(false);
const loadStudents = async () => {
try {
setLoading(true);
const response =
await api.get<StudentResponse>(
"/students"
);
setStudents(response.data.data);
} finally {
setLoading(false);
}
};
interface ApiError {
success: boolean;
message: string;
errors?: {
[field: string]: string[];
};
}
This interface can describe validation and other structured API errors.
try {
await api.get("/students");
} catch (error) {
if (axios.isAxiosError<ApiError>(error)) {
console.log(
error.response?.data.message
);
}
}
interface LoginRequest {
email: string;
password: string;
}
interface LoginResponse {
success: boolean;
message: string;
token: string;
user: {
id: number;
name: string;
email: string;
};
}
const loginData: LoginRequest = {
email: "user@example.com",
password: "123456"
};
const response =
await api.post<LoginResponse>(
"/login",
loginData
);
const token = response.data.token;
const response =
await api.get<StudentResponse>(
"/students",
{
headers: {
Accept: "application/json",
Authorization: `Bearer ${token}`
}
}
);
Headers can be added to typed Axios requests just like normal Axios requests.
API operations can be placed inside reusable functions.
const getStudents =
async (): Promise<Student[]> => {
const response =
await api.get<StudentResponse>(
"/students"
);
return response.data.data;
};
The function promises to return a Student[].
const createStudent =
async (
data: CreateStudentRequest
): Promise<Student> => {
const response =
await api.post<CreateStudentResponse>(
"/students",
data
);
return response.data.data;
};
Avoid unnecessarily using any for API responses.
// Avoid
const response: any =
await api.get("/students");
Prefer:
const response =
await api.get<StudentResponse>(
"/students"
);
This allows TypeScript to understand the response structure.
any for every API response.import axios from "axios";
export interface Student {
id: number;
name: string;
email: string;
mobile: string;
}
export interface StudentResponse {
success: boolean;
message: string;
data: Student[];
}
const api = axios.create({
baseURL: "https://example.com/api",
headers: {
Accept: "application/json"
}
});
export const getStudents =
async (): Promise<Student[]> => {
const response =
await api.get<StudentResponse>(
"/students"
);
return response.data.data;
};
export default api;
import React, {
useEffect,
useState
} from "react";
import {
View,
Text,
FlatList
} from "react-native";
import api from "./api";
interface Student {
id: number;
name: string;
email: string;
mobile: string;
}
interface StudentResponse {
success: boolean;
message: string;
data: Student[];
}
const StudentList = () => {
const [students, setStudents] =
useState<Student[]>([]);
const [loading, setLoading] =
useState<boolean>(false);
const loadStudents = async () => {
try {
setLoading(true);
const response =
await api.get<StudentResponse>(
"/students"
);
setStudents(response.data.data);
} catch (error) {
console.log(error);
} finally {
setLoading(false);
}
};
useEffect(() => {
loadStudents();
}, []);
return (
<View>
{loading && (
<Text>Loading...</Text>
)}
<FlatList
data={students}
keyExtractor={item =>
item.id.toString()
}
renderItem={({ item }) => (
<View>
<Text>{item.name}</Text>
<Text>{item.email}</Text>
<Text>{item.mobile}</Text>
</View>
)}
ListEmptyComponent={
<Text>No students found</Text>
}
/>
</View>
);
};
export default StudentList;
React Native
↓
TypeScript Request Interface
↓
Axios
↓
PHP REST API
↓
MySQL
↓
JSON Response
↓
TypeScript Response Interface
↓
React Native State
↓
FlatList / UI
TypeScript provides structure for the request and response, while Axios handles communication with the PHP REST API.
For example, a student list screen can use a typed Axios response,
store the returned Student[] in state, and display the
records using FlatList.
axios.isAxiosError().Student[].any when the API structure is known.Question: Which Axios syntax is used to specify the TypeScript type of the response?