🔎

Reactで作る簡易検索機能

3 min read

配列操作を利用した検索機能を紹介します。UI化することで利便性が一気に向上が見込まれます。

DEMO

まずはデモです。入力欄に適当なアルファベットを入力することで、続くリストが増減します。

※ DemoのサンプルデータはWikipediaのプログラミング言語を利用しています。

基本的な仕組み

基本的な仕組みはfitlerを利用した配列操作です。

["a", "b", "c"].filter((text) => {
  return text === "a";
});
// #=> ["a"];

ここからユーザー入力を受け付けるように拡張します。

let searchKeyword = "b"; // ユーザーが入力する文字列

["a", "b", "c"].filter((text) => {
  return text === searchKeyword;
});

このままだと完全一致になるため、ユーザーは検索しているキーワードを一字一句知っているため利便性は向上していません。

比較方法を部分一致に切り替えます。

let searchKeyword = "c";

["a", "b", "c"].filter((text) => {
  return new RegExp(searchKeyword).test(text); // 入力キーワードを正規表現にする
});

これで検索したい文字列に部分一致したものが残ります。

Reactの実装に起こす

コメントに書いてあるとおりですが、実際にユーザーの入力を受け付ける場合、安全に正規表現のオブジェクト(RegExp)に変換する必要があります。例えば+などの入力文字をそのままnew RegExp("*")とすると、Invalid ExpressionとなってExceptionを投げます。

また、アルファベットの場合、大文字小文字が含まれるため、うまく部分一致去せるためにはUppser CaseかLower Caseにキャストして比較するとよくマッチします。

import * as React from "react";
import "./styles.css";
import escapeStringRegexp from "escape-string-regexp";

interface Props {
  list: string[];
}

export default function App(props: Props) {
  // ユーザーの入力キーワードをState化する
  const [searchKeyword, updateSearchKeyword] = React.useState("");
  
  // 入力イベントに反応してStateを更新する
  const onInput = (event: React.FormEvent<HTMLInputElement>) => {
    // 入力キーワードをstateに格納する
    updateSearchKeyword(event.currentTarget.value);
  };

  const filteredList = props.list.filter((item) => {
    // ユーザー入力を安全に正規表現にする(このときすべて小文字化で正規化する)
    const escapedText = escapeStringRegexp(searchKeyword.toLowerCase());
    // 小文字で比較して部分一致するものだけを残す
    return new RegExp(escapedText).test(item.toLowerCase());
  });

  // あとはただ表示するだけ
  return (
    <div className="App">
      <h1>Simple keyword search</h1>
      <div>
        <label htmlFor="search-keyword">Search</label>
        <input
          id="search-keyword"
          type="text"
          onInput={onInput}
          placeholder={"input search keyword"}
        />
      </div>
      <ul className="list">
        {filteredList.map((item) => {
          return <li key={item}>{item}</li>;
        })}
      </ul>
    </div>
  );
}

ユースケース

静的サイトなど、予めデータが決まっているような場合は検索キーワードのJSONを作っておき、今回のようなフィルタリングを実施することでメニューの検索機能などが実装できます。

応用

UI部分はliタグで実装しましたが、つまるところ配列のfilterの操作しかしていません。配列のUIに対する写像としてtableで表現したり、BootstrapなどのCard UIで表現したり見せ方は色々工夫できると思います。

あとがき

あくまでも今回紹介したのは「簡易」検索機能です。いくらでも機能を盛り込んで検索UIを豪華にすることはできます。ただ、やはり開発コストがかかるのでリリースされないままお蔵入りなんてことがあります。今回紹介した程度のことであれば、知っていれば数分でできるわりに検索体験はかなり良いものになります。是非実践してみてください。