Tailwind Logo

Next.js のプロジェクトに Search の Widget を追加する(後編)

SearchNext.js

公開日: 2023-10-06

前回は Sitecore Search のウィジットを追加することができるように、言語切替えのボックスのみ準備をしました。今回は、ウィジットを追加して検索結果を表示したいと思います。

ウィジットを追加する

今回は、サイトの中でウィジットを利用することができるように、プロジェクトを変更していきます。この手順は以下のように提供されています。

まず最初に、@sitecore-search/cli をプロジェクトにインストールします。

PowerShell
npm install --save-dev @sitecore-search/cli

続いて .sc-search-settings.json というファイルを作成して、Widget を配置するパスを指定します。今回は以下のように作成しました。

JSON
{
  "components-path": "src/widgets"
}

また widget を作成するコマンドを有効にするために、package.json に以下のコードを追加してください。

JSON
  "scripts": {
    "create-widget": "sc-search new-widget"
  },

これで準備ができました。以下のコマンドを実行して、Widget のファイルを作成します。

PowerShell
npm run create-widget

実行すると以下のようにウィザード形式で質問と回答を繰り返していきます。

searchwidget01.png

今回は以下のように進めていきました。

  • 言語 - typescript
  • インプリをするエンティティ - content
  • テンプレート - Preview Search Basic
  • スタイルシート - Styled with styled-components
  • ファイル作成先 - .sc-search-settings.json で指定したフォルダでいいか? - Yes
  • コンポーネントの名前 - PreviewSearch

以下が実行結果となります。

searchwidget02.png

ファイルがフォルダの下にできました。

searchwidget03.png

ウィジットを展開する

今回作成をしたウィジットを利用するコンポーネントとして、src/components/HeaderInput/index.tsx というファイルを作成します。

TypeScript
import PreviewSearch from "@/widgets/PreviewSearch";

export default function HeaderInput() {
  return <div>{<PreviewSearch rfkId="rfkid_6"></PreviewSearch>}</div>;
}

これで作成したウィジットを呼び出すコンポーネントができました。あとはこのウィジットを利用できるように src/pages/_app.tsx のファイルを変更していきます。必要となる追加のインポートは以下の通りです。locale の呼び出しはすでに入れてありますが、別の項目が必要となっているため注意してください。

TypeScript
import locales, { Language } from "@/data/locales";
import { PageController, WidgetsProvider } from "@sitecore-search/react";
import type { Environment } from "@sitecore-search/data";
import {
  SEARCH_ENV,
  SEARCH_CUSTOMER_KEY,
  SEARCH_API_KEY,
} from "@/constants/search";
import HeaderInput from "@/components/HeaderInput";

続いて、ウィジットを利用する際に必要となるコードを追加していきます。ウィジットを利用する際に、PageController を利用して言語に関して制御することができるようになっているため、以下のように書き換えます。

TypeScript
export default function App({ Component, pageProps }: AppProps) {
  const [storageLanguage, setStorageLanguage] = useStorage(
    "lang",
    "en" as Language
  );
  const [language, setLanguage] = useState<Language>(storageLanguage);

  PageController.getContext().setLocaleLanguage(language);
  PageController.getContext().setLocaleCountry(locales[language].country);

  useEffect(() => {
    PageController.getContext().setLocaleLanguage(language);
    PageController.getContext().setLocaleCountry(locales[language].country);
    setStorageLanguage(language);
  }, [language, setStorageLanguage]);

これで準備ができました。先ほど作成したウィジットのためのコンポーネントを実装します。この際、WidgetsProvider を利用しています。

TypeScript
  return (
    <LanguageContext.Provider value={{ language, setLanguage }}>
      <WidgetsProvider
        env={SEARCH_ENV as Environment}
        customerKey={SEARCH_CUSTOMER_KEY}
        apiKey={SEARCH_API_KEY}
      >
        <LocaleSelector />
        <HeaderInput />
        <Component {...pageProps} />
      </WidgetsProvider>
    </LanguageContext.Provider>
  );

これで準備が整いました。

動作検証

実際に npm run dev を実行すると、以下のように動作することがわかります。

searchsample04.gif

ヘッダーファイルにまとめる

すでに _app.tsx ファイルに対してコンポーネントを並べている状況ですが、ヘッダーとして利用するコンポーネントをまとめていきます。まず、src/components/Header/index.tsx として以下のファイルを作成します。

TypeScript
import HeaderInput from "@/components/HeaderInput";
import LocaleSelector from "@/components/LocaleSelector";

export default function Header() {
  return (
    <div>
      <LocaleSelector />
      <HeaderInput />
    </div>
  );
}

続いて、src/pages/_app.tsx のファイルのコンポーネントを並べているところを変更するために、以下の記述を追加してください。

TypeScript
import Header from "@/components/Header";

上記のコンポーネントで利用している LocaleSelector と HeaderInput のコンポーネントの import を削除して、該当するところを <Header /> に書き換えます。

TypeScript
      <WidgetsProvider
        env={SEARCH_ENV as Environment}
        customerKey={SEARCH_CUSTOMER_KEY}
        apiKey={SEARCH_API_KEY}
      >
        <Header />
        <Component {...pageProps} />
      </WidgetsProvider>

これでヘッダーで利用するコンポーネントをヘッダーコンポーネントに集めました。動作結果は全く同じです。

まとめ

前回の言語選択のドロップダウンボックスと、ウィジットが連携をして検索結果を表示しているのを確認することができました。なお、ここまでのコードは、以下のリポジトリでブランチとして公開しています。

関連タグ