Google 検索や乗換検索サービスとかでよく見るこれ。サジェストと呼ぶのかオートコンプリートと呼ぶのか。
react-autosuggest というライブラリを使って実装してみます。
Codepen にサンプルコードがたくさんあります。
https://codepen.io/collection/DkkYaQ/
React のみの場合
Basic Usage のコードを参考に。
import React from 'react'; import { render } from 'react-dom'; import Autosuggest from 'react-autosuggest'; import './styles/index.scss'; // サジェストに表示する項目 const languages = [ { name: 'C', year: 1972 }, ... ]; // 入力値に対するサジェスト項目を取得するロジック const getSuggestions = (value) => { const inputValue = value.trim().toLowerCase(); const inputLength = inputValue.length; return inputLength === 0 ? [] : languages.filter((lang) => lang.name.toLowerCase().slice(0, inputLength) === inputValue, ); }; // サジェスト項目が Object の場合、サジェスト選択時に Object のどの項目を表示するか決める const getSuggestionValue = (suggestion) => suggestion.name; // サジェスト部分のレンダリングロジック const renderSuggestion = (suggestion) => ( <div> {suggestion.name} </div> ); class Example extends React.Component { constructor() { super(); // Autosuggest is a controlled component. // This means that you need to provide an input value // and an onChange handler that updates this value (see below). // Suggestions also need to be provided to the Autosuggest, // and they are initially empty because the Autosuggest is closed. this.state = { value: '', suggestions: [], }; } onChange = (event, { newValue }) => { this.setState({ value: newValue, }); }; // Autosuggest will call this function every time you need to update suggestions. // You already implemented this logic above, so just use it. onSuggestionsFetchRequested = ({ value }) => { console.log('onSuggestionsFetchRequested'); this.setState({ suggestions: getSuggestions(value), }); }; // Autosuggest will call this function every time you need to clear suggestions. onSuggestionsClearRequested = () => { console.log('onSuggestionsClearRequested'); this.setState({ suggestions: [], }); }; render() { const { value, suggestions } = this.state; // Autosuggest will pass through all these props to the input element. const inputProps = { placeholder: 'Type a programming language', value, onChange: this.onChange, }; // Finally, render it! return ( <Autosuggest suggestions={suggestions} onSuggestionsFetchRequested={this.onSuggestionsFetchRequested} onSuggestionsClearRequested={this.onSuggestionsClearRequested} getSuggestionValue={getSuggestionValue} renderSuggestion={renderSuggestion} inputProps={inputProps} /> ); } } render( <Example />, document.getElementById('root'), );
NOTE:スタイルを指定しないとキャプチャのように <ul><li>
のリスト表示になるので
https://codepen.io/moroshko/pen/XRgbxR を参考にスタイルを当てる必要がある。
必須 props
以下、<Autosuggest>
に必ず渡す必要があるデータや関数。
suggestions
getSuggestionValue()
renderSuggestion()
onSuggestionsFetchRequested
onSuggestionsClearRequested
なお、便宜的にサジェスト項目として扱う Object を suggestion
と表現する。↑の例だと
{ name: 'C', year: 1972 },
がサジェスト項目1個分に相当する。
- suggestions
: Array<suggestion
>
文字通り、サジェストに表示するデータのリスト。 Array であれば良い。
- getSuggestionValue()
: Function(suggestion
) -> String
サジェスト項目がクリックされたとき、または上下カーソルキーでサジェスト内容を選択したときに
input 項目に表示するテキストを決めるロジックになる。
戻り値は String じゃないといけない。
- renderSuggestion()
: Function(suggestion
) -> JSX
サジェスト項目をどのように render するか。
- onSuggestionsFetchRequested()
: Function(現在の入力値
)
ドキュメントには
Will be called every time you need to recalculate
suggestions
.
と書かれており、発火タイミングがはっきりしないけど、入力テキストが変更されたときに呼ばれる関数。
基本的にはここで state で管理している suggestions
をアップデートする。
- onSuggestionsClearRequested()
: Function()
こちらも発火タイミングが謎。サジェストを非表示にしたときに呼ばれる関数。
ここで suggestions
に []
をセットするなどしてクリアーする。
- inputProps
: Object
内部的に使われている <input>
項目へ渡す props。value
, onChange
などは基本必須になるかと。
サジェスト結果をセクションに分ける
サジェスト結果をカテゴライズして表示したいということがある。Yahoo!路線情報 のような。
この場合、suggestions
として渡すデータは
const languages = [ { title: '1970s', languages: [ { name: 'C', year: 1972 } ] }, ... ];
というように一段ネストが深くなる。
title
がセクションタイトル、languages
がそのセクションにおける suggestions
となる。
新たに以下の props を指定する。
- multiSection
: bool
true にする。
- renderSectionTitle()
: Function(section
) -> JSX
セクションのタイトルの render ロジック。
↑の例で title
を指定する場合は
function renderSectionTitle(section) { return ( <strong>{section.title}</strong> ); }
- getSectionSuggestions()
: Function(section
) -> suggestions
セクションごとの suggestions
を取得するロジック。
↑の例の場合は
function getSectionSuggestions(section) { return section.languages; }
Redux と組み合わせる
https://github.com/zaki-yama/react-autosuggest-sample を参照。
基本的に value
, suggestions
を Redux の state で管理し、onChange
, onSuggestionsFetchRequested
, onSuggestionsClearRequested
のタイミングで action を dispatch することになる。