Vue InstantSearchでサーバーへのempty query(空クエリ)を発生させないようにする方法

Algoliaの Vue InstantSearch の Conditional Requests というページに記載されていますが、デフォルトの挙動として👇のようになります。

InstantSearch makes another first request to show the initial results on an empty query”

InstantSearchは最初に空クエリを発行してその結果を表示させます

Conditional Requests

空クエリを発行するのではなく、ユーザーに文字を入力された場合だけクエリを発行したい、といった場合にどうすれば良いか?という部分について書いていきたいと思います。

結論から言うと、👇のように普通にJavaScriptで毎回検索リクエストが発生されるタイミングで空クエリかどうかを判別して、空クエリだった場合は、サーバーにリクエストを送らずに何もヒットしていない0件の結果を自分でreturnしてしまうという感じです。

    if (requests.every(({ params }) => !params.query)) {
      return Promise.resolve({
        results: requests.map(() => ({
          hits: [],
          nbHits: 0,
          nbPages: 0,
          processingTimeMS: 0,
        })),
      });
    }

ローカルで動作する環境を構築

githubからサンプル用のリポジトリをcloneしてきます

$ git clone https://github.com/algolia/vue-instantsearch-v2-starter
Cloning into 'vue-instantsearch-v2-starter'...
remote: Enumerating objects: 86, done.
remote: Total 86 (delta 0), reused 0 (delta 0), pack-reused 86
Unpacking objects: 100% (86/86), done.
TOK-MBP-ES:vueis eiji.shinohara$ ls -l
total 0
drwxr-xr-x  14 eiji.shinohara  staff  448 Feb 14 14:48 vue-instantsearch-v2-starter

そのディレクトリに行ってyarn installして、

$ yarn install
yarn install v1.19.1
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
warning "@vue/cli-plugin-babel > babel-loader@8.0.4" has unmet peer dependency "webpack@>=2".
warning "@vue/cli-plugin-eslint > eslint-loader@2.1.1" has unmet peer dependency "webpack@>=2.0.0 <5.0.0".
[4/4] 🔨  Building fresh packages...
✨  Done in 20.21s.

個人的な(会社のラップトップの都合で?)アレでポート番号を8888でローカルで起動するようにします

$ cat vue.config.js
module.exports = {
    devServer: {
        port: 8888,
        disableHostCheck: true,
    },
};

で👇してやると、

$ yarn run serve
〜略〜
 DONE  Compiled successfully in 2462ms                                                    4:46:20 PM
  App running at:
  - Local:   http://localhost:8888/
  - Network: http://172.16.162.150:8888/
  Note that the development build is not optimized.
  To create a production build, run yarn build.

ってことで、それっぽくなってきました👇

App.vueを改修してempty queryをハンドリング

App.vueの export default の部分をバラすといいますか、fine-tune出来るようにしてあげます。今のところ挙動は変わりません。

const algoliaClient = algoliasearch(
  'xxxx',
  'xxxxxxxxx'
);
const searchClient = {
  search(requests) {
    return algoliaClient.search(requests);
  },
};
export default {
  data() {
    return {
      searchClient,
    };
  },
};

空クエリだったら、という分岐を入れてalertしてみます。

const searchClient = {
  search(requests) {
    if (requests.every(({ params }) => !params.query)) {
      // 空クエリだった場合の処理
      alert('empty query');
    }
    return algoliaClient.search(requests);
  },
};

アラートが表示されています

それではalertではなく、ゼロ件を返すようにしてみます。

const searchClient = {
  search(requests) {
    if (requests.every(({ params }) => !params.query)) {
      return Promise.resolve({
        results: requests.map(() => ({
          hits: [],
          nbHits: 0,
          nbPages: 0,
          processingTimeMS: 0,
        })),
      });    }
    return algoliaClient.search(requests);
  },
};

そうすると、デフォルトでは何も表示されませんし、検索窓にカーソルを合わせても検索結果は何も表示されていません。

もちろん検索バーで文字を入力すれば、as you typeで高速な検索体験となります!

まとめ

検索バーがあるページを開いたタイミングでAlgoliaのサーバー側にリクエストを飛ばしたくない、というようなシチュエーションにおいては、Vue側でempty queryかどうかを判別して、emptyの場合はサーバー側に連携せずに、その場でゼロ件の結果をreturnしてあげるようにすることで、不必要なクエリ発行数の増加を防ぐことが出来るかなと思います。

コメント

タイトルとURLをコピーしました