【JavaScript】【React】React Autosuggestを使ってみる

2022-11-22JavaScript,React,React Autosuggest

はじめに

Reactでオートサジェスト(オートコンプリート)機能を実現するコンポーネントである、React Autosuggestについて、使い方を調べてみたのでこのエントリで紹介したいと思います。

環境

  • React Autosuggest version 10.1.0

React Autosuggestとは

Reactでオートサジェスト(オートコンプリート)機能を実現するコンポーネントです。入力部分に文字を入力すると、しその下部に、入力内容に応じた候補一覧が表示されます。また、表示された候補の1つをクリックすることで、入力部分に、選択した候補に応じた内容が入力されます。

ちなみにauto suggestと名前がついていますが、コンポーネント自体にキーワードを絞り込むような機能は一切なく、ユーザーが実装しなければなりません。

React Autosuggest公式

簡単な使い方

使い方は公式のチュートリアルを見れば大体わかると思いますが、少し手を加え、サーバーと通信することにします。また、クラスコンポーネントで書かれているので、関数コンポーネントで書き直してみます。

サーバーは次のような動作をします。

  • 入力した文字列をサーバーにGETで渡す
  • サーバーは渡された文字列で始まる文字列の配列をJSONで返す

サーバーは次のような言語名の一覧を持っているとします。ここから、サーバーは渡された文字列で始まる言語名のみをクライアントへ返します。たとえば、"C"を渡した場合は、"C", "C++", "C#", "COBOL"を返します。

[
    "Basic",
    "C",
    "C++",
    "C#",
    "COBOL",
    "Go",
    "Fortran",
    "Java",
    "JavaScript",
    "Julia",
    "MATLAB",
    "Perl",
    "PHP",
    "Python",
    "R",
    "Ruby",
    "Rust"
]

使用例

React Autosuggestを使用した例を以下に示します。サーバーとのやり取りにはaxiosを使いました。

import { React, useState } from "react";
import ReactDOM from "react-dom";
import axios from "axios";
import Autosuggest from "react-autosuggest";

const getSuggestionValue = (suggestion) => {
    return suggestion;
};

const renderSuggestion = (suggestion) => {
    return <span>{suggestion}</span>;
};

const App = () => {
    const [inputValue, setInputValue] = useState("");
    const [suggestions, setSuggestions] = useState([]);

    const onChange = (event, { newValue, method }) => {
        setInputValue(newValue);
    };

    const onSuggestionsFetchRequested = ({ value, reason }) => {
        const axiosApi = axios.create({
            headers: {
                "Content-Type": "application/json",
            },
        });

        axios.get("/key-suggestions", {
            params: {
                key: value,
            },
        })
        .then((res) => {
            setSuggestions(res.data);
        })
        .catch((error) => {
            setSuggestions([]);
        });
    };

    const onSuggestionsClearRequested = () => {
        setSuggestions([]);
    };

    const inputProps = {
        placeholder: "文字を入力してください",
        value: inputValue,
        onChange: onChange,
    };

    return (
        <Autosuggest
            suggestions={suggestions}
            onSuggestionsFetchRequested={onSuggestionsFetchRequested}
            onSuggestionsClearRequested={onSuggestionsClearRequested}
            getSuggestionValue={getSuggestionValue}
            renderSuggestion={renderSuggestion}
            inputProps={inputProps}
        />
    );
};

ReactDOM.render(<App />, document.getElementById("app"));

React Autosuggestでは、いくつか指定できるプロパティがあります。以下は指定必須のプロパティです。

プロパティ動作
suggestions表示する候補一覧を指定します
onSuggestionsFetchRequested候補一覧が変更される時に呼び出されるコールバック関数を指定します
onSuggestionsClearRequested候補一覧がクリアされる時に呼び出されるコールバック関数を指定します
getSuggestionValue候補がクリックされた場合の値を返す関数を指定します
renderSuggestion表示される候補のJSXを返す関数を指定します
inputProps入力部分に渡すプロパティを設定します。<input>要素に使用できるプロパティは渡せるようです。最低限valueonChangeが必要です

ほかに以下のプロパティがあります。詳細は公式ドキュメントをご覧ください。

プロパティ動作
containerPropsコンテナ(入力部分の外側にある<div>要素)に渡すプロパティを指定します
onSuggestionSelected候補が選択された時に呼び出されるコールバック関数を指定します
onSuggestionHighlighted候補がハイライトされた時に呼び出されるコールバック関数を指定します
shouldRenderSuggestions入力部分にフォーカスされている時に、候補一覧を表示するかどうか判定するためのコールバック関数を指定します
alwaysRenderSuggestions常に候補一覧を表示する場合はtrueを指定します
highlightFirstSuggestion候補一覧の先頭をハイライトする場合はtrueを指定します
focusInputOnSuggestionClick候補一覧をクリックしたときに入力部分をフォーカスしたままにする場合はfalseを指定します
multiSectionセクションごとに候補を表示する場合に使用します
renderSectionTitlemultiSectionを使用する場合に必須です
getSectionSuggestionsmultiSectionを使用する場合に必須です
renderInputComponent入力部分をカスタマイズするときに使用します
renderSuggestionsContainer候補一覧部分をカスタマイズするときに使用します
themeコンポーネントにCSSを当てるときに使用します
id複数の<Autosuggest>を使うときに使用します

スタイルを当てる

React Autosuggestは独自のスタイルを持っていませんので、自前でスタイルを当てる必要があります。公式ドキュメントによると、react-themeableに対応しており、themeに対応するクラス名でCSSを記述することによりスタイルを当てることができます。

デフォルトでは以下のクラスが対応しています。

{
    container:                "react-autosuggest__container",
    containerOpen:            "react-autosuggest__container--open",
    input:                    "react-autosuggest__input",
    inputFocused:             "react-autosuggest__input--focused",
    suggestionsContainer:     "react-autosuggest__suggestions-container",
    suggestionsContainerOpen: "react-autosuggest__suggestions-container--open",
    suggestionsList:          "react-autosuggest__suggestions-list",
    suggestion:               "react-autosuggest__suggestion",
    suggestionFirst:          "react-autosuggest__suggestions--first",
    suggestionHighlighted:    "react-autosuggest__suggestions--highlighted",
    sectionContainer:         "react-autosuggest__section-container",
    sectionContainerFirst:    "react-autosuggest__section-container--first",
    sectionTitle:             "react-autosuggest__section-title",
}

Global CSS

デフォルトで設定されているクラス名でCSSを記述します。また、独自のクラス名でCSSを記述した場合は、次のようにthemeオブジェクトを指定し、<Autosuggest>コンポーネントのプロパティとして渡します。

const theme = {
    container: containerに対応する独自のクラス名,
    ...
};

return <Autosuggest theme={theme} ... />;

CSS Modules

別のファイルにCSSを記述します。クラス名はテーマと同じにします。CSSのファイル名は.module.cssで終わる必要があるので注意が必要です。拡張子の件は、公式にもreact-themeableのドキュメントにも書いてありませんが、.cssだけだとうまくいきませんでした。

.container { ... }
.containerOpen { ... }
.input { ... }
...

作成したファイルをインポートし、<Autosuggest>コンポーネントのプロパティとして渡します。

import theme from "sample.module.css";

return <Autosuggest theme={theme} ... />;

Bootstrap

Bootstrapで使うには、以下の記事が参考になります。

おわりに

Reactでオートサジェスト(オートコンプリート)機能を実現するコンポーネントである、React Autosuggestについて、使い方を調べてみました。公式ドキュメントが古く、注意する点がありましたので、こちらの記事が参考になれば幸いです。