Search Functionality with useQuery

Marickian
By -
0
Comprehensive Guide to Implementing Search Functionality with useQuery

Implementing Search Functionality with useQuery

When building modern web applications, search functionality is often crucial for filtering and retrieving data efficiently. React Query, with its useQuery hook, provides a powerful tool for managing data fetching and caching. In this guide, we will explore how to implement a search feature using useQuery and how to handle state, input, and re-rendering effectively.

Step-by-Step Overview

Let's break down the implementation of the search functionality. We will set up a form with an input field for users to type their search term, and based on that input, we'll fetch the relevant data using useQuery. We will also make sure that when the input changes, the search results update in real-time, thanks to React's state management.

1. Setting up the Input Form

The first step is to create an input field where users can type their search query. We will also add a button to reset the search, bringing back all the results. Here's the basic structure of our form:

            
<div class="search-container">
    <input 
        type="text" 
        placeholder="Enter your search term..." 
        value={searchValue} 
        onChange={handleSearchChange} 
        required 
    />
    <button 
        type="button" 
        onClick={resetSearch} 
        disabled={isPending}
    >
        {isPending ? "Please wait..." : "Reset"}
    </button>
</div>
            
        

The <input> is a controlled component, meaning its value is bound to the state, which we will set up in the next step. The onChange event will handle the input changes, updating the state whenever the user types something. The <button> is used to reset the search results back to their original state, and we will disable it when a query is still pending.

2. Managing the State with useState

Since we're dealing with controlled inputs, we need to set up a state variable to hold the search term. This is done using the useState hook. Here's how we define it:

            
const [searchValue, setSearchValue] = useState('');
const isPending = false; // Simulating the pending state from the query
            
        

We initialize searchValue with an empty string. This value will be updated every time the user types into the search input. To handle that, we need to define a function handleSearchChange, which will update the state based on the input value:

            
const handleSearchChange = (event) => {
    setSearchValue(event.target.value);
};
            
        

Now, every time a user types something in the input field, the searchValue state will update, triggering a re-render.

3. Fetching Data with useQuery

The core of our search functionality lies in data fetching. For that, we'll use the useQuery hook from React Query. We will pass the search value as a query parameter, ensuring that whenever the user enters a search term, a new request is made to fetch the filtered data.

            
const { data, error, isLoading, isPending } = useQuery(
    ['items', searchValue], // Query key with searchValue
    () => fetchItems(searchValue), // Function to fetch the data
    { 
        enabled: !!searchValue, // Only run the query if searchValue is not empty
        staleTime: 300000 // Cache the results for 5 minutes
    }
);
            
        

Here's what's happening in this useQuery call:

  • Query key: We use an array where the first item is a static key ('items') and the second item is the dynamic search value. This ensures that each time the searchValue changes, a new query is triggered.
  • Fetch function: The function fetchItems is responsible for fetching the data based on the search term. It could be an API call that passes the search value to filter the results.
  • Enabled option: This ensures that the query only runs if the searchValue is not empty. This prevents unnecessary queries from being made when there's no input.
  • Cache management: Using the staleTime option, we cache the results for 5 minutes. This helps prevent unnecessary refetches when the same query is made multiple times within the cache period.

4. Handling Results and Errors

Once the data is fetched, we need to display it. We also handle any potential errors or loading states. Here’s how we can conditionally render different UI states based on the query’s status:

            
if (isLoading) {
    return <p>Loading...</p>;
}

if (error) {
    return <p>Error loading data.</p>;
}

if (data) {
    return (
        <ul>
            {data.map((item) => (
                <li key={item.id}>{item.name}</li>
            ))}
        </ul>
    );
}
            
        

Here we check if the data is still loading, if an error occurred during the fetch, or if we have data to display. If data is successfully fetched, we map over the results and render them in a list.

5. Resetting the Search

The reset functionality is simple: we clear the search input and restore the original (unfiltered) dataset. This is achieved by resetting the searchValue to an empty string, which triggers a new query that fetches all data (since no search term is provided).

            
const resetSearch = () => {
    setSearchValue('');
};
            
        

By setting the search value back to an empty string, the query re-fetches the full dataset, and the search input is cleared.

Conclusion

Implementing a search feature with useQuery in React Query is a powerful and efficient way to handle data fetching and caching. With just a few steps, we were able to create a functional search input that updates the results in real time, manage state with useState, and handle data fetching, loading, and error states with useQuery.

This setup provides a responsive and user-friendly experience, allowing users to quickly find the information they need. The caching and re-fetching capabilities of React Query make this solution both performant and scalable for real-world applications.

Post a Comment

0Comments

Post a Comment (0)