DatoCMS Site Search > React search widget

React search widget

In addition to the low-level API request presented in the previous section, our react-datocms package also includes a React hook that you can use to render a full-featured Site Search widget on your website.

You're in charge of the UI!

The hook only handles the form logic: you are in complete and full control of how your form renders down to the very last component, class or style.

Setup

First of all, install the required npm packages in your React project:

npm install --save @datocms/cma-client-browser

You can then use the useSiteSearch hook like this:

import { useSiteSearch } from 'react-datocms';
import { buildClient } from '@datocms/cma-client-browser';
const client = buildClient({ apiToken: 'YOUR_API_TOKEN' });
const { state, error, data } = useSiteSearch({
client,
buildTriggerId: '7497',
// optional: you can omit it you only have one locale, or you want to find results in every locale
initialState: { locale: 'en' },
// optional: to configure how to present the part of page title/content that matches the query
highlightMatch: (text, key, context) =>
context === 'title' ? (
<strong key={key}>{text}</strong>
) : (
<mark key={key}>{text}</mark>
),
// optional: defaults to 8 search results per page
resultsPerPage: 10,
});

Please follow the react-datocms documentation to read more about at the configuration options and the data returned by the hook.

Complete example

The following example uses the react-paginate npm package to simplify the handling of pagination. You can build your own pagination using the data.totalPages property to get the total number of pages, state.page to get the current page, and state.setPage(page) to trigger a page change.

import { useState } from 'react';
import { buildClient } from '@datocms/cma-client-browser';
import ReactPaginate from 'react-paginate';
import { useSiteSearch } from 'react-datocms';
const client = buildClient({ apiToken: 'YOUR_API_TOKEN' });
function App() {
const [query, setQuery] = useState('');
const { state, error, data } = useSiteSearch({
client,
initialState: { locale: 'en' },
buildTriggerId: '7497',
resultsPerPage: 10,
});
return (
<div>
<form
onSubmit={(e) => {
e.preventDefault();
state.setQuery(query);
}}
>
<input
type="search"
value={query}
onChange={(e) => setQuery(e.target.value)}
/>
<select
value={state.locale}
onChange={(e) => {
state.setLocale(e.target.value);
}}
>
<option value="en">English</option>
<option value="it">Italian</option>
</select>
</form>
{!data && !error && <p>Loading...</p>}
{error && <p>Error! {error}</p>}
{data && (
<>
{data.pageResults.map((result) => (
<div key={result.id}>
<a href={result.url}>{result.title}</a>
<div>{result.bodyExcerpt}</div>
<div>{result.url}</div>
</div>
))}
<p>Total results: {data.totalResults}</p>
<ReactPaginate
pageCount={data.totalPages}
forcePage={state.page}
onPageChange={({ selected }) => {
state.setPage(selected);
}}
activeClassName="active"
renderOnZeroPageCount={() => null}
/>
</>
)}
</div>
);
}