How to integrate Meilisearch with React InstantSearch

    Meilisearch allows you to search through your data via a RESTful API. When in development mode, it provides a search preview where you can test your search settings without implementing a front end.

    Animated gif in which a user types "trumen show" and sees "The Truman Show" as the top result

    The search preview is a development tool and not suited for end-users. In this tutorial, you’ll learn how to create a custom search interface using two open-source tools:

    Introducing the dataset

    This guide uses a dataset of restaurants generated with faker, a library that generates fake data, and uses Unsplash image URLs. Each restaurant has the following fields:

    The front end will look like this:

    Searching through a list of restaurants

    Requirements

    1. A running instance of Meilisearch (v >= 1.x) with the restaurants’ dataset indexed. If you need help with this part, you can follow our quick start guide.
    2. A React environment with the following packages installed:
    yarn add @meilisearch/instant-meilisearch@^0.11.1 instantsearch.css@^8.0.0 react-instantsearch-dom@^6.39.1
    
    NOTE

    If you’re using newer versions of the packages, you may want to check their changelogs.

    To create a single-page React application, use Create React App.

    Implementation

    For this guide, you only need two files: App.js and index.js. App.js will contain your app's code, and index.js will initialize your React App.

    Your index.js file should look like this:

    import React from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    import App from './App';
    
    ReactDOM.render(
      <React.StrictMode>
        <App />
      </React.StrictMode>,
      document.getElementById('root')
    );
    

    You shouldn't have to modify index.js.

    Your App.js file should look like this:

    import "instantsearch.css/themes/algolia-min.css";
    import React from "react";
    import {
      InstantSearch,
      InfiniteHits,
      SearchBox,
      Stats,
      Highlight
    } from "react-instantsearch-dom";
    import "./App.css";
    import { instantMeiliSearch } from "@meilisearch/instant-meilisearch";
    
    const searchClient = instantMeiliSearch(
      "<your Meilisearch host>",
      "<your Meilisearch API key>"
    );
    
    const App = () => (
      <div className="ais-InstantSearch">
        <h1>Restaurants Demo with Meilisearch</h1>
        <InstantSearch indexName="restaurant" searchClient={searchClient}>
          <Stats />
          <SearchBox />
          <InfiniteHits hitComponent={Hit} />
        </InstantSearch>
      </div>
    );
    
    const Hit = ({ hit }) => (
      <div key={hit.id}>
        <div className="hit-name">
          <Highlight attribute="name" hit={hit} />
        </div>
        <p className="hit-categories"><Highlight attribute="categories" hit={hit} /></p>
        <div className="hit-image">
          <img src={hit.picture} alt={hit.name} width="200px" />
          <p className="image-credit">Picture by <a href={hit.picture_author_profile_link}>{hit.picture_author}</a> on <a href="https://unsplash.com/?utm_source=restaurants_demo&utm_medium=referral">Unsplash</a></p>
        </div>
        <div className="hit-description">
          <Highlight attribute="description" hit={hit} />
        </div>
      </div>
    );
    
    export default App;
    

    Importing the required components

    The following lines of code import the components and the search client, along with CSS styling:

    import "instantsearch.css/themes/algolia-min.css";
    import React from "react";
    import {
      InstantSearch,
      InfiniteHits,
      SearchBox,
      Stats,
      Highlight
    } from "react-instantsearch-dom";
    import "./App.css";
    import { instantMeiliSearch } from "@meilisearch/instant-meilisearch";
    

    Initializing the search client

    Next, you need to initialize the search client that will communicate with Meilisearch. Add your Meilisearch credentials: host and API key, as the first and second parameters of the instantMeilisearch function.

    const searchClient = instantMeiliSearch(
      "<your Meilisearch host>",
      "<your Meilisearch API key>"
    );
    
    NOTE

    In production environments, make sure to secure your instance and use a read-only key.

    Adding components

    The following code adds the necessary components:

    const App = () => (
      <div className="ais-InstantSearch">
        <h1>Restaurants Demo with Meilisearch</h1>
        <InstantSearch indexName="restaurant" searchClient={searchClient}>
          <Stats />
          <SearchBox />
          <InfiniteHits hitComponent={Hit} />
        </InstantSearch>
      </div>
    );
    
    const Hit = ({ hit }) => (
      <div key={hit.id}>
        <div className="hit-name">
          <Highlight attribute="name" hit={hit} />
        </div>
        <p className="hit-categories"><Highlight attribute="categories" hit={hit} /></p>
        <div className="hit-image">
          <img src={hit.picture} alt={hit.name} width="200px" />
          <p className="image-credit">Picture by <a href={hit.picture_author_profile_link}>{hit.picture_author}</a> on <a href="https://unsplash.com/?utm_source=restaurants_demo&utm_medium=referral">Unsplash</a></p>
        </div>
        <div className="hit-description">
          <Highlight attribute="description" hit={hit} />
        </div>
      </div>
    );
    
    export default App;
    

    The Hit component

    const Hit = ({ hit }) => (
      <div key={hit.id}>
        <div className="hit-name">
          <Highlight attribute="name" hit={hit} />
        </div>
        <p className="hit-categories"><Highlight attribute="categories" hit={hit} /></p>
        <div className="hit-image">
          <img src={hit.picture} alt={hit.name} width="200px" />
          <p className="image-credit">Picture by <a href={hit.picture_author_profile_link}>{hit.picture_author}</a> on <a href="https://unsplash.com/?utm_source=restaurants_demo&utm_medium=referral">Unsplash</a></p>
        </div>
        <div className="hit-description">
          <Highlight attribute="description" hit={hit} />
        </div>
      </div>
    );
    

    Conclusion

    That's it—you have a fully functioning search front end powered by InstantSearch. To go further, you might want to use filters to create a faceted search interface and allow users to refine search results based on restaurant categories.

    NOTE

    Prefer some other flavor of JavaScript? Check out this list of Meilisearch front-end integrations.

    Encountering any issues? Don't hesitate to use the help channel on Discord. 🙌