Lesson 106 of 158 – React Native API Search
67%

React Native API Search

Search is an important feature in mobile applications. Instead of displaying every record, a user can enter a keyword and request matching records from the REST API. React Native can send the search value to a PHP API using Fetch, and the PHP API can search the MySQL database.

Note: In this lesson, we will build the basic search flow: React Native Search Input → API Query → PHP/MySQL Search → JSON Response → FlatList.

1. What is API Search?

API search means sending a search keyword to the server and receiving only the records that match that keyword.

React Native
      ↓
Search Keyword
      ↓
PHP REST API
      ↓
MySQL Search
      ↓
JSON Response
      ↓
FlatList

2. Why Use Server-Side Search?

  • Useful for large datasets.
  • Reduces the amount of data sent to the mobile device.
  • Searches directly in the database.
  • Works well with pagination.
  • Can search multiple fields.
  • Keeps the mobile application simpler.

3. Search Query Parameter

A search keyword can be sent as a query parameter.

GET /api/students.php?search=rahul

Here, search is the parameter and rahul is the search value.

4. React Native Search State

useState can store the text entered by the user.

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

Every time the user types, the search state can be updated.

5. Search TextInput

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

TextInput provides the search field for the user.

6. Sending Search with Fetch

const response = await fetch(
    `${API_URL}?search=${search}`
);

const result =
    await response.json();

setStudents(
    result.data || []
);

7. URL Encoding Search Text

Search text may contain spaces or special characters. Encode it before adding it to a URL.

const query =
    encodeURIComponent(search);

const response = await fetch(
    `${API_URL}?search=${query}`
);

This helps create a valid URL when the search contains special characters.

8. PHP Reading the Search Parameter

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

The PHP API can use this value to build the database search condition.

9. MySQL LIKE Search

MySQL LIKE can be used to find records containing a particular keyword.

SELECT id, name, email
FROM students
WHERE name LIKE ?

The search value can be provided as a prepared statement parameter.

10. PHP LIKE Parameter

11. Searching Multiple Columns

A search can check more than one column.

SELECT id, name, email, course
FROM students
WHERE name LIKE ?
   OR email LIKE ?
   OR course LIKE ?

This allows one keyword to search multiple fields.

12. Multiple Search Parameters

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

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

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

13. Search API Response

The PHP API can return the matching records as JSON.

{
    "success": true,
    "data": [
        {
            "id": 1,
            "name": "Rahul Kumar",
            "email": "rahul@example.com",
            "course": "React Native"
        }
    ]
}

14. Display Search Results in FlatList

<FlatList
    data={students}

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

    renderItem={({ item }) => (

        <View>

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

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

        </View>
    )}
/>

15. Search Button

The user can press a button to send the search request.

<Button
    title="Search"
    onPress={searchStudents}
/>

16. Search Function

async function searchStudents() {

    const query =
        encodeURIComponent(search);

    const response =
        await fetch(
            `${API_URL}?search=${query}`
        );

    const result =
        await response.json();

    setStudents(
        result.data || []
    );
}

17. Handling Empty Search

The application should decide what to do when the search box is empty.

async function searchStudents() {

    if (search.trim() === "") {

        loadStudents();

        return;
    }

    // Perform search...
}

In this example, an empty search loads all students.

18. Search Loading State

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

async function searchStudents() {

    setLoading(true);

    try {

        const query =
            encodeURIComponent(search);

        const response =
            await fetch(
                `${API_URL}?search=${query}`
            );

        const result =
            await response.json();

        setStudents(
            result.data || []
        );

    } catch (error) {

        console.log(
            error.message
        );

    } finally {

        setLoading(false);

    }
}

19. Search Error Handling

async function searchStudents() {

    setLoading(true);
    setError("");

    try {

        const query =
            encodeURIComponent(search);

        const response =
            await fetch(
                `${API_URL}?search=${query}`
            );

        const result =
            await response.json();

        if (!response.ok) {

            throw new Error(
                result.message ||
                "Search failed"
            );
        }

        setStudents(
            result.data || []
        );

    } catch (error) {

        setError(
            error.message
        );

    } finally {

        setLoading(false);

    }
}

20. Search with useEffect

A search can also be triggered automatically when the search value changes.

useEffect(() => {

    if (search.trim() === "") {
        loadStudents();
        return;
    }

    searchStudents();

}, [search]);

For real applications, automatic searching should usually be combined with debouncing so that an API request is not sent for every keystroke.

21. Search with Debouncing

Debouncing waits for the user to stop typing before making the API request.

useEffect(() => {

    const timer =
        setTimeout(() => {

            if (search.trim() === "") {

                loadStudents();

            } else {

                searchStudents();

            }

        }, 500);

    return () =>
        clearTimeout(timer);

}, [search]);

The 500 millisecond delay is an example and can be adjusted.

22. Search with Pagination

Search can be combined with pagination when the result contains many records.

GET /api/students.php
    ?search=rahul
    &page=1
    &limit=10

The PHP API can use the search value together with LIMIT and OFFSET.

23. Search and Authentication

If the search endpoint is protected, the React Native application can send the JWT token.

const response = await fetch(
    `${API_URL}?search=${query}`,
    {
        headers: {
            "Accept":
                "application/json",

            "Authorization":
                `Bearer ${token}`
        }
    }
);

24. Search and FlatList

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

<FlatList
    data={students}

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

    renderItem={({ item }) => (

        <View>

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

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

        </View>

    )}

    ListEmptyComponent={
        <Text>
            No matching students found.
        </Text>
    }
/>

25. Search API with PHP PDO

<?php

header(
    "Content-Type: application/json"
);

require_once "../db.php";

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

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

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

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

$data =
    $stmt->fetchAll(
        PDO::FETCH_ASSOC
    );

echo json_encode([
    "success" => true,
    "data" => $data
]);

The prepared statement keeps the search value separate from the SQL command.

26. Search API with Loading and Error States

async function searchStudents() {

    setLoading(true);
    setError("");

    try {

        const query =
            encodeURIComponent(
                search.trim()
            );

        const response =
            await fetch(
                `${API_URL}?search=${query}`
            );

        const result =
            await response.json();

        if (!response.ok) {

            throw new Error(
                result.message ||
                "Search request failed"
            );
        }

        if (!result.success) {

            throw new Error(
                result.message ||
                "Unable to search"
            );
        }

        setStudents(
            result.data || []
        );

    } catch (error) {

        setError(
            error.message
        );

    } finally {

        setLoading(false);

    }
}

27. Search Result Count

The API can also return the number of matching records.

{
    "success": true,
    "data": [
        {
            "id": 1,
            "name": "Rahul"
        }
    ],
    "meta": {
        "total": 1
    }
}

React Native can display the total result count.

<Text>
    Results: {total}
</Text>

28. Complete React Native Search Example

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

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

const API_URL =
    "https://example.com/api/students.php";

export default function StudentSearch() {

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

    const [students, setStudents] =
        useState([]);

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

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

    async function searchStudents(
        keyword = search
    ) {

        setLoading(true);
        setError("");

        try {

            const query =
                encodeURIComponent(
                    keyword.trim()
                );

            const response =
                await fetch(
                    `${API_URL}?search=${query}`
                );

            const result =
                await response.json();

            if (!response.ok) {

                throw new Error(
                    result.message ||
                    "Search failed"
                );
            }

            if (!result.success) {

                throw new Error(
                    result.message ||
                    "Unable to search"
                );
            }

            setStudents(
                result.data || []
            );

        } catch (error) {

            setError(
                error.message
            );

        } finally {

            setLoading(false);

        }
    }

    useEffect(() => {

        const timer =
            setTimeout(() => {

                searchStudents();

            }, 500);

        return () =>
            clearTimeout(timer);

    }, [search]);

    return (

        <View>

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

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

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

            <FlatList

                data={students}

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

                renderItem={({ item }) => (

                    <View>

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

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

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

                    </View>

                )}

                ListEmptyComponent={
                    !loading ? (
                        <Text>
                            No matching
                            students found.
                        </Text>
                    ) : null
                }

            />

        </View>
    );
}

29. Common API Search Mistakes

  • Sending the search value without URL encoding.
  • Building SQL using string concatenation.
  • Not using prepared statements.
  • Searching only on the mobile device when server-side search is required.
  • Sending an API request for every keystroke without debouncing.
  • Not handling empty search values.
  • Not handling loading and error states.
  • Not handling empty search results.
  • Forgetting pagination for large result sets.
  • Not checking the API response status.
  • Not authenticating protected search endpoints.

30. Complete API Search Flow

React Native
      ↓
  TextInput
      ↓
 Search Keyword
      ↓
  URL Encode
      ↓
     Fetch
      ↓
GET /students.php?search=rahul
      ↓
    PHP API
      ↓
   Validate
      ↓
  Prepared SQL
      ↓
    MySQL
      ↓
Matching Records
      ↓
   JSON Response
      ↓
setStudents()
      ↓
    FlatList
      ↓
 Display Results

This pattern can be extended with pagination, sorting, filtering, authentication, and TypeScript API types.

📌 Key Points

  • API search sends a keyword to the server.
  • Query parameters are commonly used for search.
  • Use encodeURIComponent() for URL search values.
  • PHP can read search parameters using $_GET.
  • MySQL LIKE can be used for keyword searching.
  • Use PDO prepared statements for search queries.
  • One search keyword can search multiple columns.
  • Use TextInput for entering search text.
  • Use FlatList for displaying search results.
  • Debouncing can reduce unnecessary API requests.
  • Search can be combined with pagination and authentication.
  • Always handle loading, errors, and empty results.

🧠 Quick Quiz

Question: Which query parameter can commonly be used to send a search keyword to a REST API?