Adding Search
Reading
Adding a search feature to our API
Let's consider adding a search feature to our API to satisfy the
search/filter in our UI.
We could add another endpoint such as GET /api/Restaurants/search, but we
already have an endpoint that represents what we want: the list of
restaurants, we want a variant of that list.
In this case, we can use the query parameter feature of HTTP to our advantage,
and it is precisely what this feature supports.
We will update the definition of the GetRestaurants method as such:
[HttpGet]public async Task<ActionResult<IEnumerable<Restaurant>>> GetRestaurants(string filter)
The string filter will be populated with the value of a query parameter
named filter if present, otherwise the variable filter will be null.
We can use this to our advantage in the implementation. If the filter variable
is null, we return all restaurants. Otherwise, we add a Where method to only
include the restaurant where the Name property contains the phrase in the
filter variable.
if (filter == null){return await _context.Restaurants.ToListAsync();}else{return await _context.Restaurants.Where(restaurant => restaurant.Name.ToLower().Contains(filter.ToLower())).ToListAsync();}
Updating the UI to allow for filtering
First, let's update Restaurants.tsx to contain a state for the filter text.
const [filterText, setFilterText] = useState('')
Then we will update the <input> tag
<inputtype="text"placeholder="Search..."value={filterText}onChange={function (event) {setFilterText(event.target.value)}}/>
Update the useQuery to take the filterText into consideration
- First, we change the unique identifier for the query to
['restaurants', filterText]. This allows any caching thatreact-querydoes to be dependent on our filter text. - Then we dynamically change the URL based on the filter. If there is no filterText, we use the default URL, otherwise, we send a query parameter with our filter text.
const { data: restaurants = [] } = useQuery<RestaurantType[]>(['restaurants', filterText],async function () {const response = await fetch(filterText.length === 0? '/api/restaurants': `/api/restaurants?filter=${filterText}`)return response.json()})