How to Build a Search Page with Live Results

Search pages are a common part of websites. They enable visitors to browse the site and find information. Let’s learn how to build a search page that updates results as the content of the search box changes.

Build a Search Page: Initial Component and Search State

First, create a new component and add a search useState hook to it. This state will store our search query. It could also store other filters and sorting that must be provided to the server. We want it to all be in the same object because react query will get fresh results whenever this state changes. The component should look like the following:


const SearchContents = () => {
  const [search, setSearch] = useState<{ query: string }>();
}

Setting Up the React Query

Now that we have the query in state we need to use it to search. This page will use react-query because it provides good results caching and will update search anytime our search query updates. First, we have to add a query provider component for react-query. Set up a new query provider and a page that wraps our search contents like this:


const queryClient = new QueryClient();

const QueryProvider: React.FC = ({ children }) => {
  return (
    {children}
  );
};

export const SearchPage = () => {
  return (
    <QueryProvider>
      <SearchContents />
    </QueryProvider>
  );
};

Now that we have the provider around our SearchContents component, we can add the useQuery hook to it.


const SearchContents = () => {
  const [search, setSearch] = useState<{ query: string }>();

  const storySearchResponse = useQuery(["storySearch", search], async () => {
    return (await axios.create({ baseURL: "/api" })).post(`/search/stories`, {
      query: search?.query,
    });
  });


}

Getting Results

The last step is adding the input box and displaying the results coming back from the server. The query from the useState hook will be the value of the search box. And, when the contents of the box change, it will call the setSearch function. The most bare-bones version will look something like this:


<>
   <input 
     value={search?.query} 
     onChange={(event) => {setSearch({ query: 
     event.target.value }); }}
   /> 
   <div>
     {storySearchResponse.data}
   </div>
 </>

The full component we have so far looks like this:


import axios from "axios";
import { useState } from "react";
import { QueryClient, QueryClientProvider, useQuery } from "react-query";

const queryClient = new QueryClient();

const QueryProvider: React.FC = ({ children }) => {
  return (
    {children}
  );
};

export const SearchPage = () => {
  return (
    <QueryProvider>
      <SearchContents />
    </QueryProvider>
  );
};


const SearchContents = () => {
  const [search, setSearch] = useState<{ query: string }>();

  const storySearchResponse = useQuery(["storySearch", search], async () => {
    return (await axios.create({ baseURL: "/api" })).post(`/search/stories`, {
      query: search?.query,
    });
  });

return <>
   <input 
     value={search?.query} 
     onChange={(event) => {setSearch({ query: 
     event.target.value }); }}
   /> 
   <div>
     {storySearchResponse.data}
   </div>
 </>
}

This will form a base for a live updating search page. It will need to be updated and customized further.

Next Steps

The next steps include styling up the input and search result display, not many people want to read through an object to find the results, and adding better guards around the query request. What are some other features you look for in a search page?

Conversation

Join the conversation

Your email address will not be published. Required fields are marked *