27th December 2022 • 3 min read
How to setup Algolia search with Remix
Burak Tarım
In this article, we will build a simplified version of our client Heavybit's library browse module.
We built it using Algolia search with Remix.
You can check the full working version from here.
Also, please don't forget to read our case study with our client Heavybit.
To build a simplified version of the library browse page, we are going to follow these steps;
1. Create an empty Remix project
2. Create the library browse component
3. Create custom hits and search box
4. Add widgets to the library browse
5. Apply some styling
1npx create-remix@latest
We will use algoliasearch and react-instantsearch-hooks-web packages to make algoliasearch work in our project.
You can read more about instant-search from Algolia docs.
We are going to install them with these commands;
1npm i react-instantsearch-hooks-web algoliasearch
We are going to use tailwind CSS to style this project.
You can add tailwind CSS by following these steps in tailwind docs.
Create a React component and Import InstantSearch from "react-instantsearch-hooks-web", init the searchClient and the index name. We will use custom components in this InstantSearch component.
1// Import packages
2
3import { InstantSearch } from "react-instantsearch-hooks-web";
4import algoliasearch from "algoliasearch/lite";
5
6// Inıt the search client
7
8const searchClient = algoliasearch("APP_ID", "SEARCH_KEY");
9
10export default function LibraryBrowse() {
11 return (
12 <div>
13 <InstantSearch indexName="INDEX_NAME" searchClient={searchClient}>
14 {/** Custom widgets */}
15 </InstantSearch>
16 </div>
17 );
18}
19
Now we will create the hits and the search box widget with instant search hooks.
3.1 Custom hits component
In this component, we are going to use useHits() hook. You can read more about it from Algolia docs.
All we will do is loop through the hits array and create our custom list.
1import { useHits } from "react-instantsearch-hooks-web";
2
3export default function CustomHits() {
4 const { hits } = useHits();
5
6 return (
7 <ul>
8 {hits.map((hit: any) => (
9 <li className="list-none" key={hit.objectID}>
10 <img src={hit.image} />
11 {hit.title}
12 {hit.content?.substr(0, 100)}
13 </li>
14 ))}
15 </ul>
16 );
17}
18
3.2 Create custom search box
In this component, we are going to use useSearchBox() hook. Here are the docs about it.
We will use the refine and the clear functions of this hook. We need to call refine when the user types something and clear when the user wants to delete the query.
1import React from "react";
2import { useSearchBox } from "react-instantsearch-hooks-web";
3
4export default function CustomSearchBox() {
5 const { refine, clear } = useSearchBox();
6 const [val, setVal] = React.useState("");
7
8 React.useEffect(() => {
9 refine(val);
10 }, [val]);
11
12 return (
13 <div>
14 <input
15 type={"text"}
16 value={val}
17 onChange={(e) => {
18 setVal(e.target.value);
19 }}
20 />
21 <button
22 onClick={() => {
23 clear();
24 setVal("");
25 }}
26 >
27 X
28 </button>
29 </div>
30 );
31}
32
Now we can import our custom widgets and add them to InstantSearch with pagination.
1// Import packages
2
3import { InstantSearch, Pagination } from "react-instantsearch-hooks-web";
4import algoliasearch from "algoliasearch/lite";
5import CustomSearchBox from "./CustomSearchBox";
6import CustomHits from "./CustomHits";
7
8// Inıt the search client
9
10const searchClient = algoliasearch("APP_ID", "SEARCH_KEY");
11
12export default function LibraryBrowse() {
13 return (
14 <div>
15 <InstantSearch indexName="INDEX_NAME" searchClient={searchClient}>
16 {/** widgets */}
17 <CustomSearchBox />
18 <CustomHits />
19 <Pagination />
20 {/** widgets */}
21 </InstantSearch>
22 </div>
23 );
24}
25
Now we can clear everything under the ./app/routes/index.tsx file and import our LibraryBrowse component.
1import LibraryBrowse from "~/components/LibraryBrowse";
2
3export default function Index() {
4 return (
5 <div>
6 <LibraryBrowse></LibraryBrowse>
7 </div>
8 );
9}
10
If you go to http://localhost:3000, you can see a fully functional library browse component, and search and pagination work well.