This page is a work in progress.You can help improve it. →

Adding Search

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 the NavBar to contain a state for the filter text.

const [filterText, setFilterText] = useState('')

Then we will update the <input> tag

<input
type="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 that react-query does 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()
}
)

Files Updated

© 2017 - 2021; Built with ♥ in St. Petersburg, Florida.