Filtering: Searching the List of Links

In this section, we’ll implement a search feature and learn about the filtering capabilities of our GraphQL API.

Preparing the React components

The search will be available under a new route and implemented in a new React component.

Again, this is a pretty standard setup. You’re rendering an input field where the user can type a search string.

The Search component uses the useState hook to hold a search term supplied by the user. The setSearchFilter functions is called in the onChange event on the input to update this value.

The component is also looking for a variable called data which it iterates over to render Link components with the search results. We’ll define and execute the query a bit later.

For the user to be able to comfortably navigate to the search functionality, let’s also add a new navigation item to the Header.

We can now navigate to the search feature using the new button in the Header:

We can navigate to the search feature

Great, let’s now go back to the Search component and see how we can implement the actual search.

Filtering Links

This query looks similar to the feed query that’s used in LinkList. However, this time it takes in an argument called filter that will be used to constrain the list of links we want to retrieve.

The actual filter is built and used in the feed resolver which is implemented in server/src/resolvers/Query.js:

async function feed(parent, args, context, info) {
  const where = args.filter
    ? {
        OR: [
          { description: { contains: args.filter } },
          { url: { contains: args.filter } }
    : {};

  const links = await{
    skip: args.skip,
    take: args.take,
    orderBy: args.orderBy

  const count = await{ where });

  return {
    id: 'main-feed',

module.exports = {

Note: To understand what’s going on in this resolver, check out the Node tutorial.

In this case, two where conditions are specified: A link is only returned if either its url contains the provided filter or its description contains the provided filter. Both conditions are combined using Prisma’s OR operator.

Perfect, the query is defined! But this time we actually want to load the data every time the user hits the OK button, not upon the initial load of the component. To do this, we’ll use a hook supplied by Apollo called useLazyQuery. This hook performs a query in the same way the useQuery hook does but the difference is that it must be executed manually. This is perfect for our situation––we want to execute the query when the OK button is clicked.

Let’s include useLazyQuery and execute it when the OK button is clicked.

const Search = () => {
  const [searchFilter, setSearchFilter] = useState('');
  const [executeSearch, { data }] = useLazyQuery(
  return (
          onChange={(e) => setSearchFilter(}
          onClick={() =>
              variables: { filter: searchFilter }
      {data &&, index) => (
          <Link key={} link={link} index={index} />

We’ll want to be sure to import useLazyQuery at the top of the file.

import { useLazyQuery } from '@apollo/client';

The implementation is almost trivial! We’re executing the FEED_SEARCH_QUERY manually and retrieving the links from the response that’s returned by the server. These links are put into the component’s state so that they can be rendered.

Go ahead and test the app by running yarn start in a terminal and navigating to http://localhost:3000/search. Then type a search string into the text field, click the OK button and verify the links that are returned fit the filter conditions.

Unlock the next chapter
What's the purpose of the 'withApollo' function?
You use it to send queries and mutations to a GraphQL server
When wrapped around a component, it injects the 'ApolloClient' instance into the component's props
You have to use it everywhere where you want to use Apollo functionality
It parses GraphQL code