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 thesearchValue
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