Lesson 156 of 158 – Project Search Screen
98%

Project Search Screen

In this lesson, we will create the Student Search screen for our Student Management mobile application using React Native, TypeScript, Axios, FlatList, and the PHP REST API.

The user will enter a search keyword and the application will send that keyword to the PHP API. The server will search the MySQL database and return matching students.

Project Goal: Create a complete Student Search screen with API search, TypeScript, Axios, FlatList, loading, error, empty states, and pagination support.

1. Student Search Flow

Search Screen
      ↓
Enter Keyword
      ↓
Axios GET Request
      ↓
PHP REST API
      ↓
MySQL Search
      ↓
JSON Response
      ↓
TypeScript
      ↓
FlatList
      ↓
Matching Students

2. Why Use Server-Side Search?

Server-side search is useful when the database contains a large number of student records.

  • The mobile app does not need to download every student.
  • The database performs the search.
  • Less data is transferred.
  • Search works well with pagination.
  • It can be combined with filtering and sorting.

3. Student Interface

interface Student {
    id: number;
    name: string;
    email: string;
    mobile: string;
    course: string;
    address: string;
}

4. Search Response Interface

interface PaginationMeta {
    page: number;
    limit: number;
    total: number;
    total_pages: number;
}

interface StudentSearchResponse {
    success: boolean;
    data: Student[];
    meta: PaginationMeta;
}

5. Import React Native Components

import React, {
    useEffect,
    useState
} from "react";

import {
    View,
    Text,
    TextInput,
    FlatList,
    ActivityIndicator,
    TouchableOpacity,
    RefreshControl
} from "react-native";

6. Search State

const [search, setSearch] =
    useState("");

const [students, setStudents] =
    useState<Student[]>([]);

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

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

7. Pagination State

const [page, setPage] =
    useState(1);

const [loadingMore, setLoadingMore] =
    useState(false);

const [hasMore, setHasMore] =
    useState(true);

Pagination allows the application to load search results page by page.

8. Search API URL

GET /api/students.php?search=rahul

The search query parameter contains the keyword entered by the user.

9. Axios Search Request

const response =
    await api.get<StudentSearchResponse>(
        "/students.php",
        {
            params: {
                search: search,
                page: 1,
                limit: 10
            }
        }
    );

setStudents(
    response.data.data
);

10. Search Function

const searchStudents =
    async (keyword: string) => {

    try {

        setLoading(true);
        setError("");

        const response =
            await api.get<StudentSearchResponse>(
                "/students.php",
                {
                    params: {
                        search: keyword,
                        page: 1,
                        limit: 10
                    }
                }
            );

        setStudents(
            response.data.data
        );

        setPage(1);

        setHasMore(
            response.data.meta.page
            < response.data.meta.total_pages
        );

    } catch (error) {

        setError(
            "Unable to search students."
        );

    } finally {

        setLoading(false);

    }
};

11. Search TextInput

<TextInput
    placeholder="Search students..."
    value={search}
    onChangeText={setSearch}
/>

The TextInput stores the current search keyword.

12. Search Button

<TouchableOpacity
    onPress={() =>
        searchStudents(search)
    }
>

    <Text>
        Search
    </Text>

</TouchableOpacity>

13. Clear Search

const clearSearch =
    async () => {

    setSearch("");

    await searchStudents("");
};

Clearing the search keyword can reload the normal student list.

14. PHP Read Search Parameter

$search =
    trim($_GET['search'] ?? '');

PHP reads the search keyword from the URL query parameter.

15. SQL LIKE Search

$keyword = "%" . $search . "%";

$stmt = $pdo->prepare(
    "SELECT
        id,
        name,
        email,
        mobile,
        course,
        address
     FROM students
     WHERE
        name LIKE ?
        OR email LIKE ?
        OR mobile LIKE ?
        OR course LIKE ?"
);

$stmt->execute([
    $keyword,
    $keyword,
    $keyword,
    $keyword
]);

The API can search multiple student fields using the SQL LIKE operator.

16. Why Use Prepared Statements?

Search keywords come from users, so they should never be directly inserted into an SQL query.

$stmt = $pdo->prepare(
    "SELECT * FROM students
     WHERE name LIKE ?"
);

$stmt->execute([
    "%" . $search . "%"
]);

Prepared statements help prevent SQL injection.

17. Display Search Results with FlatList

<FlatList
    data={students}

    keyExtractor={item =>
        item.id.toString()
    }

    renderItem={({ item }) => (

        <View>

            <Text>
                {item.name}
            </Text>

            <Text>
                {item.email}
            </Text>

            <Text>
                {item.course}
            </Text>

        </View>
    )}
/>

18. Empty Search Results

{!loading &&
    students.length === 0 && (
        <Text>
            No students found.
        </Text>
    )}

An empty state clearly informs the user that no student matches the search keyword.

19. Search Loading State

{loading && (
    <ActivityIndicator
        size="large"
    />
)}

Display a loading indicator while the search request is being processed.

20. Search Error Handling

try {

    const response =
        await api.get<StudentSearchResponse>(
            "/students.php",
            {
                params: {
                    search,
                    page: 1,
                    limit: 10
                }
            }
        );

} catch (error) {

    if (
        axios.isAxiosError(error)
    ) {

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

            setError(
                "Session expired."
            );

        } else {

            setError(
                error.response?.data?.message
                || "Search failed."
            );
        }

    } else {

        setError(
            "Network error."
        );
    }
}

21. Search Pagination

const loadMore =
    async () => {

    if (
        loadingMore ||
        !hasMore
    ) {
        return;
    }

    const nextPage =
        page + 1;

    try {

        setLoadingMore(true);

        const response =
            await api.get<StudentSearchResponse>(
                "/students.php",
                {
                    params: {
                        search,
                        page: nextPage,
                        limit: 10
                    }
                }
            );

        setStudents(
            previous => [
                ...previous,
                ...response.data.data
            ]
        );

        setPage(nextPage);

        setHasMore(
            nextPage
            < response.data.meta.total_pages
        );

    } finally {

        setLoadingMore(false);

    }
};

22. FlatList onEndReached

<FlatList
    data={students}

    keyExtractor={item =>
        item.id.toString()
    }

    renderItem={({ item }) => (
        <Text>
            {item.name}
        </Text>
    )}

    onEndReached={loadMore}

    onEndReachedThreshold={0.5}
/>

When the user reaches the bottom of the search results, the next page can be loaded.

23. Search and Pagination Together

GET /students.php
    ?search=react
    &page=2
    &limit=10

The server can apply the search condition first and then return the requested page of matching records.

24. Reset Pagination After New Search

When the search keyword changes, pagination should start from page one.

setPage(1);

setHasMore(true);

searchStudents(
    newKeyword
);

This prevents the application from requesting page 5 of a completely new search.

25. Search Student Actions

Search results can provide the same actions as the normal Student List.

  • View student details.
  • Edit student.
  • Delete student.
navigation.navigate(
    "StudentDetails",
    {
        id: item.id
    }
);

26. Complete Search Function

const searchStudents =
    async (keyword: string) => {

    try {

        setLoading(true);
        setError("");

        const response =
            await api.get<StudentSearchResponse>(
                "/students.php",
                {
                    params: {
                        search:
                            keyword.trim(),
                        page: 1,
                        limit: 10
                    }
                }
            );

        setStudents(
            response.data.data
        );

        setPage(1);

        setHasMore(
            response.data.meta.page
            < response.data.meta.total_pages
        );

    } catch (error) {

        if (
            axios.isAxiosError(error)
        ) {

            setError(
                error.response?.data?.message
                || "Search failed."
            );

        } else {

            setError(
                "Network error."
            );
        }

    } finally {

        setLoading(false);

    }
};

27. Complete Search Screen

const StudentSearchScreen =
    ({ navigation }: any) => {

    const [search, setSearch] =
        useState("");

    const [students, setStudents] =
        useState<Student[]>([]);

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

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

    const searchStudents =
        async () => {

        try {

            setLoading(true);
            setError("");

            const response =
                await api.get<StudentSearchResponse>(
                    "/students.php",
                    {
                        params: {
                            search:
                                search.trim(),
                            page: 1,
                            limit: 10
                        }
                    }
                );

            setStudents(
                response.data.data
            );

        } catch (error) {

            setError(
                "Unable to search students."
            );

        } finally {

            setLoading(false);

        }
    };

    return (

        <View>

            <Text>
                Search Students
            </Text>

            <TextInput
                placeholder="Search by name, email, mobile or course"
                value={search}
                onChangeText={setSearch}
            />

            <TouchableOpacity
                onPress={searchStudents}
            >

                <Text>
                    Search
                </Text>

            </TouchableOpacity>

            {loading && (
                <ActivityIndicator />
            )}

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

            {!loading &&
                students.length === 0 && (
                    <Text>
                        No students found.
                    </Text>
            )}

            <FlatList
                data={students}

                keyExtractor={item =>
                    item.id.toString()
                }

                renderItem={({ item }) => (

                    <TouchableOpacity
                        onPress={() =>
                            navigation.navigate(
                                "StudentDetails",
                                {
                                    id: item.id
                                }
                            )
                        }
                    >

                        <Text>
                            {item.name}
                        </Text>

                        <Text>
                            {item.email}
                        </Text>

                        <Text>
                            {item.course}
                        </Text>

                    </TouchableOpacity>
                )}
            />

        </View>
    );
};

28. Search Screen Security and Performance

  • Protect the API with JWT.
  • Use prepared statements.
  • Validate search parameters.
  • Limit the number of returned records.
  • Use pagination for large datasets.
  • Do not expose sensitive student information.
  • Use HTTPS in production.
  • Avoid sending unnecessary requests.
  • Consider database indexes for frequently searched fields.

29. Complete Search Architecture

Search Screen
      ↓
TextInput
      ↓
Search Keyword
      ↓
Axios
      ↓
JWT Authorization
      ↓
PHP API
      ↓
$_GET['search']
      ↓
PDO Prepared Statement
      ↓
MySQL LIKE Search
      ↓
Pagination
      ↓
JSON Response
      ↓
TypeScript
      ↓
FlatList
      ↓
Student Results
      ↓
Details / Edit / Delete

30. Project Search Screen Summary

The Student Search screen allows users to quickly find students stored in the MySQL database through the REST API.

  • React Native provides the search interface.
  • TextInput collects the search keyword.
  • Axios sends the keyword to the PHP API.
  • PHP reads the search query parameter.
  • PDO prepared statements safely perform the database search.
  • SQL LIKE can search multiple fields.
  • TypeScript interfaces describe the response.
  • FlatList displays matching students.
  • Pagination handles large search results.
  • Search results can connect to details, edit, and delete screens.
  • The next lesson will cover the complete authentication flow.

📌 Key Points

  • Use server-side search for large student datasets.
  • Send the keyword through a query parameter.
  • Use Axios to call the search API.
  • Use SQL LIKE for keyword searching.
  • Always use prepared statements.
  • Use TypeScript interfaces for API data.
  • Use FlatList to display search results.
  • Combine search with pagination.
  • Reset pagination when a new search starts.
  • Protect the search API with JWT authentication.

🧠 Quick Quiz

Question: Which SQL operator is commonly used for keyword searching in our Student API?