並べ替え(ソート)

最終更新: 2022年02月11日

概要

SortByのカスタムウィジェットを作成します。

ライブデモ

カスタムウィジェットの作成

事前に Tailwind CSS と React Hook Formの導入が必要です。

components/custom-sort-by.tsx
import { Listbox, Transition } from '@headlessui/react'; import { CheckIcon, SelectorIcon } from '@heroicons/react/outline'; import React, { Fragment } from 'react'; import { connectSortBy } from 'react-instantsearch-dom'; import { classNames } from '../lib/class-names'; const SortBy = ({ currentRefinement, items, refine, }: { items: { label: string; value: string; }[]; currentRefinement: string; refine: (value: string) => void; }) => { return ( <Listbox value={currentRefinement} onChange={(value) => refine(value)}> {({ open }) => ( <div className="flex items-center space-x-2"> <Listbox.Label className="block text-sm font-medium text-gray-700"> 表示順 </Listbox.Label> <div className="relative w-40"> <Listbox.Button className="bg-white relative w-full border border-gray-300 rounded-md shadow-sm pl-3 pr-10 py-2 text-left cursor-default focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"> <span className="block truncate"> {items.find((item) => item.value === currentRefinement)?.label} </span> <span className="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none"> <SelectorIcon className="h-5 w-5 text-gray-400" aria-hidden="true" /> </span> </Listbox.Button> <Transition show={open} as={Fragment} leave="transition ease-in duration-100" leaveFrom="opacity-100" leaveTo="opacity-0" > <Listbox.Options className="absolute z-10 mt-1 w-full bg-white shadow-lg max-h-60 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm"> {items.map((item) => ( <Listbox.Option key={item.value} className={({ active }) => classNames( active ? 'text-white bg-indigo-600' : 'text-gray-900', 'cursor-default select-none relative py-2 pl-3 pr-9' ) } value={item.value} > {({ selected, active }) => ( <> <span className={classNames( selected ? 'font-semibold' : 'font-normal', 'block truncate' )} > {item.label} </span> {selected ? ( <span className={classNames( active ? 'text-white' : 'text-indigo-600', 'absolute inset-y-0 right-0 flex items-center pr-4' )} > <CheckIcon className="h-5 w-5" aria-hidden="true" /> </span> ) : null} </> )} </Listbox.Option> ))} </Listbox.Options> </Transition> </div> </div> )} </Listbox> ); }; const CustomSortBy = connectSortBy(SortBy); export default CustomSortBy;

ポイントは以下です。

  • currentRefinement で現在のソート条件を受け取って反映
  • items でソート条件のリストを取得
  • refine でソート条件を反映

カスタムウィジェットの使用

InstantSearchタグの中に設置してください。

<CustomSortBy defaultRefinement={router.query.sortBy || 'dev_users_desc'} items={[ { label: '最新順', value: 'dev_users_desc', }, { label: '古い順', value: 'dev_users_asc', }, ]} />

items にソート条件を指定しています。 value にはインデックス管理で設定したレプリカを指定してください。