1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

debounceを使って、入力後にFetch処理(Material UI の Autocomplete で複数選択を Fetch で候補検索しながら選択していくサンプル)

Last updated at Posted at 2022-01-15

初めに

タイトルが説明的でかつ長い、、
debounceを使ったAutocompleteがあまりにもひどかったので、きちんとそのあたりも含めての見直し記事
前回アップしているのは削除済み

こんな感じのもの

autocomplete_multi.gif
※画面側の動作確認のために、サーバー側はFastAPI側でGoogleに候補検索をかけにいっています

コード

App.js
import { useState, useEffect } from "react";
import { TextField, Autocomplete, Stack } from "@mui/material";
import { debounce } from "lodash";
import axios from "axios";

const App = () => {
  // 前回のキーワード
  const [beforeString, setBeforeString] = useState("");
  // 表示候補(本来はreduxのuseSelectorなんかでデータを管理する)
  const [resultOptions, setResultOptions] = useState([]);
  // 選択されている内容
  const [autocompleteValues, setAutocompleteValues] = useState([]);
  // リクエストするURL
  const baseUrl = "http://localhost:8000/api/search/candidate/words/";
  // 変更が止まった後、指定時間(ミリ秒)後処理を行う
  const term = 500;
  const debounceSearchHandler = debounce(
    (changeValue) => searchMethod(changeValue),
    term
  );

  // 検索処理
  const searchMethod = async (changeValue) => {
    setBeforeString(changeValue);
    // 内容が同じ場合は処理しない
    if (changeValue.length > 0 && beforeString !== changeValue) {
      // FetchしてAutocompleteのoptionsの内容を取得する処理
      // [{title: keyword1}, {title: keyword2}, ...] が返ってくることを想定
      const responce = await axios.get(`${baseUrl}${changeValue}`);
      setResultOptions([...responce.data]);
    } else {
      // オートコンプリートの内容初期化
      setResultOptions([]);
    }
  };

  // 選択データが変わったときの処理
  const selectedChange = (event, selectedValue) => {
    // 選択されているオートコンプリート内容変更
    setAutocompleteValues([...selectedValue]);
    // オートコンプリートの内容初期化
    setResultOptions([]);
  };

  // 選択データの内容確認
  useEffect(() => {
    console.log("autocompleteValues", autocompleteValues);
  }, [autocompleteValues]);

  return (
    <Stack sx={{ width: 500 }}>
      <Autocomplete
        multiple // 複数選択
        freeSolo // 開閉をなくす
        options={resultOptions}
        onInputChange={(e, changeValue) => {
          debounceSearchHandler(changeValue);
        }} // テキスト内容変更時
        onChange={selectedChange} // 選択状態変更時
        renderInput={(params) => (
          <TextField
            {...params}
            placeholder="候補入力"
            InputProps={{
              ...params.InputProps,
              type: "search",
            }} // 全角入力時のオートコンプリートを出さない対策
          />
        )}
        filterOptions={(options) => options} // オートコンプリートの検索処理をなくす
        getOptionLabel={(option) => option.title}
      />
    </Stack>
  );
};

export default App;

テストのサーバー側

※FastAPIで作成

main.py
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
import json
import uvicorn
import os
from candidate import requestWords

app = FastAPI()

# クロス設定
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


@app.get("/api/search/candidate/words/{input}")
def read_item(input: str):
    keyWords = requestWords.getCandidateWords(input)
    keyMap = []
    for word in keyWords:
        addKeywordMap = {"title": word}
        keyMap.append(addKeywordMap)

    return keyMap


if __name__ == "__main__":
    uvicorn.run(app)

candidate/requestWords.py
import pprint
import requests
from lxml import etree
import numpy as np
import pandas as pd


def getCandidateWords(specWord: str):

    print(specWord)

    # 単語格納用
    google_suglist = []

    # オートコンプリートのデータを取得する
    google_r = requests.get(
        "https://www.google.com/complete/search",
        params={
            "q": specWord,
            "hl": "ja",
            "ie": "utf_8",
            "oe": "utf_8",
            "output": "toolbar",
        },
    )

    google_root = etree.XML(google_r.text)

    google_sugs = google_root.xpath("//suggestion")
    google_sugstrs = [s.get("data") for s in google_sugs]

    for ss in google_sugstrs:
        google_suglist.append(ss)

    return google_suglist

終わりに

とりあえず、動作確認大事

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?