Sitecore Search with React UI SDK


The Sitecore Search SDK now has UI components for React.

There are a few different components and variants and you include them in your project by running a commandline which generates the source files in your project

Create components with CLI

There is a very nice and detailed guide in the documentation1

The path for where to place the generated components are controlled by a configuration file, so it is simple to place them in the right place for your project. This configuration file is only used by the CLI.

1
2
3
{
  "components-path": "src/feature/sitecore-search/components"
}

The CLI provides several choices before the components are generated so you get the best fit for your solution. You have to choose between both javascript/typescript, what is the content entity (product or content), and how should the generated components be styles (it can be both no styling, plain css, css modules, styled-components)

There are several components available and there is a Storybook with the components2

Configuration

The SDK comes with a WidgetsProvider that handles configuration of the components with the right configuration etc.

SearchProvider.tsx

 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
import type { JSX, ReactNode } from 'react';
import { WidgetsProvider } from '@sitecore-search/react';
import config from '@/config';

function SearchProvider({ children }: ChildrenProps): JSX.Element {
  if (!config.searchApiKey || !config.searchApiHost || !config.searchCustomerKey) {
    console.warn('Missing config for Sitecore Search', config);
    return <>{children}</>;
  }

  return (
    <WidgetsProvider
      env={config.searchEnv}
      customerKey={config.searchCustomerKey}
      apiKey={config.searchApiKey}
      serviceHost={config.searchApiHost}
      debug={true}
      useToken={true}
    >
      {children}
    </WidgetsProvider>
  );
}

export { SearchProvider };

Insert Search components in Sitecore

Ok now we want to be able to insert those components in Sitecore.

In the Customer Engagement Console aka. Sitecore Search you want to setup and configure various widgets eg. create boosting rules etc. When inserting a search component in Sitecore we want to link to that specific configuration, by using the rfkId.

Therefore I created a data source template in Sitecore with just this field and components in Sitecore.

1
2
3
4
5
import { TextField } from '@sitecore-jss/sitecore-jss-nextjs';

export type SearchWidgetReference = {
  'Rfk Id': TextField;
};

One very important detail I found was, that the Search components only supports client side rendering, not server side. This was only shown in production build, as when running next dev everything is client side rendered.

To work around this, I used the useEffet React hook to ensure, this only runs client side. Things might be simpler with app router, but as we were using Sitecore JSS, we are on the pages router.

 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
import type { JSX } from 'react';
import { ComponentProps } from 'types/component-props';
import { SearchWidgetReference } from '../types/SearchWidgetReference';
import SearchResultsWithLayoutOptionWidget from './SearchResultsWithLayoutOption';

export type SearchComponentProps = ComponentProps & {
  fields: SearchWidgetReference;
};

export const SearchResultsWithInput = (props: SearchComponentProps): JSX.Element => {
  const id = props.fields['Rfk Id']?.value as string;

  const [data, setData] = useState<boolean>(false);
  useEffect(() => {
    setData(true);
  }, []);

  if (!id) {
    return <div className="search" data-msg="Missing Rfk Id"></div>;
  }

  return (
    <div className="search">
      {!data ? (
        <div className="loading"></div>
      ) : (
        <SearchProvider>
          <SearchResultsWithLayoutOptionWidget rfkId={id}></SearchResultsWithLayoutOptionWidget>
        </SearchProvider>
      )}
    </div>
  );
};

Sorting options

The generated components include sorting, a default sort option is configuration as a property. However, before sorting works you need to configure the sorting options, otherwise you will receive validation error:

1
2
3
4
5
6
7
8
9
{
    "message": "Validation errors",
    "code": 102,
    "type": "bad_request",
    "severity": "HIGH",
    "details": {
        "validation_error_1": "sorting option 'name_asc' not configured"
    }
}

The necessary steps to enable a sorting option was:

  1. Configure attributes for sorting
  2. Setup sorting options
  3. Enable sorting options in Global Widget setting
  4. Ensure your configuration is published
  5. Content must be reindexed

Theme

By specifying a few colors with the theme functionality we got components that we could show to the client. Of course we could have made some custom styling ourselves, the theme colors ends up as css variables, so it can easily be integrated.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  const { style } = createTheme({
    palette: {
      primary: {
        main: '#007919',
        light: '#4cb87d',
        dark: '#005610',
        contrastText: '#000',
      },
    },
  });

  return (
    <WidgetsProvider
      env={config.searchEnv}
      customerKey={config.searchCustomerKey}
      apiKey={config.searchApiKey}
      serviceHost={config.searchApiHost}
      debug={true}
      useToken={true}
    >
      <div style={style}>{children}</div>
    </WidgetsProvider>
  );