Concepts / Building Search UI / Server-side rendering
Oct. 30, 2019

Server-side Rendering

You are currently reading the documentation for React InstantSearch V6. Read our migration guide to learn how to upgrade from V5 to V6. You can still find the V5 documentation for this page.

Server-side rendering typically improves SEO and performance. When using server-side rendering, your initial web content is generated on the server: browsers download pages with HTML content already in place.

React InstantSearch is compatible with server-side rendering. We provide an API that works with any server-side rendering solution.

Native

We provide an API called findResultsState, available at react-instantsearch-dom/server.

findResultsState is a function that retrieves a resultsState object. The function takes two arguments:

  • a component that contains the instantSearch widget and all the widgets that have to be mounted on the page.
  • a “props” argument, which accepts:
    • searchClient (required): the search client provided by Algolia (the same one that you pass to InstantSearch).
    • indexName (required): the same index name that you pass to InstantSearch.
    • searchState: provides your initial state to resultsState. For example, it could be set to { searchState: { query: 'chair' } }. Typically used for URL sync. Make sure App passes the initial searchState prop to your instantsearch component.
    • other props are passed to the component in the first argument.

We split this guide into three parts:

  • App.js: the shared main React component between the server and the browser.
  • server.js: a simple Node http server: the main server entry.
  • browser.js: the main browser entry. Ultimately gets compiled to bundle.js.

App.js

App.js is the main entry point to your React application, it exports an component.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import React from 'react';
import { InstantSearch, SearchBox, Hits } from 'react-instantsearch-dom';

function App({ searchClient, searchState, resultsState, onSearchParameters }) {
  return (
    <InstantSearch
      indexName="indexName"
      searchClient={searchClient}
      searchState={searchState}
      resultsState={resultsState}
      onSearchParameters={onSearchParameters}
    >
      <SearchBox />
      <Hits />
    </InstantSearch>
  );
}

export { App };

Exporting <App> makes the component available to both the browser and server code.

If you are syncing a searchState to your url for proper routing, pass a searchState to the InstantSearch component.

server.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import React from 'react';
import { createServer } from 'http';
import { renderToString } from 'react-dom/server';
import algoliasearch from 'algoliasearch/lite';
import { findResultsState } from 'react-instantsearch-dom/server';
import { App } from './App';

const searchClient = algoliasearch('YourApplicationID', 'YourSearchOnlyAPIKey');

const server = createServer(async (req, res) => {
  const searchState = { query: 'chair' };
  const resultsState = await findResultsState(App, {
    searchClient,
    searchState,
    indexName: 'indexName',
  });
  const initialState = { searchState, resultsState };
  const html = renderToString(<App {...initialState} />);

  res.send(
    `
<!doctype html>
<html>
  <body>
    <h1>Awesome server-side rendered search</h1>
    <did id="root">${html}</div>
    <script>window.__APP_INITIAL_STATE__ = ${JSON.stringify(appInitialState)}</script>
    <script src="bundle.js"></script> <!-- this is the build of browser.js -->
  </body>
</html>
`
  );
});

server.listen(8080);

To use JSX and import statements, you must transpile your server-side code (for example, with Babel). The __APP_INITIAL_STATE__ variable ensures that what was sent by the server matches what the browser expects (through a checksum).

browser.js

This last file creates the link between server-side rendering and the application on the browser.

1
2
3
4
5
6
7
8
9
10
11
import React from 'react';
import { render } from 'react-dom';
import { App } from './App';
import algoliasearch from 'algoliasearch/lite';

const searchClient = algoliasearch('YourApplicationID', 'YourSearchOnlyAPIKey');

render(
  <App {...window.__APP_INITIAL_STATE__} searchClient={searchClient} />,
  document.querySelector('#root')
);

Express + ReactDOMServer

Express is a minimal and flexible Node.js web application framework. It’s widely adopted in the Node.js ecosystem. An example of React InstantSearch and Express is available on our Github repository.

Next.js

Next.js is a framework that wraps and abstracts the more complicated parts of SSR. An example of React InstantSearch and Next.js is available on our Github repository.

</section>

Did you find this page helpful?