[TIL]9月30日検索


フリー掲示板、物品販売掲示板、コミュニティのほとんどの投稿を使用するサイトは検索機能をサポートしています.
設定によっては、タイトルのみを検索したり、コンテンツのみを検索したり、タイトル+コンテンツを検索したり、複雑なフィルタを使用して検索したりする場合もあります.
基本検索機能
検索機能の完全なコード
import { gql, useQuery } from "@apollo/client";
import { useState } from "react";
import styled from "@emotion/styled";
import { v4 as uuidv4 } from "uuid";
const FETCH_BOARDS = gql`
  query fetchBoards($search: String, $page: Int) {
    fetchBoards(search: $search, page: $page) {
      _id
      writer
      title
      createdAt
    }
  }
`;
const Column = styled.span`
  padding: 0px 50px;
`;
const Page = styled.span`
  padding: 0px 10px;
  cursor: pointer;
`;
export default function SearchPage() {
  const { data, refetch } = useQuery(FETCH_BOARDS);
  const [mySearch, setMySearch] = useState();
  const [myKeyWord, setMyKeyword] = useState();
  function onChangeSearch(event) {
    setMySearch(event.target.value);
  }
  function onClickSearch() {
    refetch({ search: mySearch, page: 1 });
    setMyKeyword(mySearch);
  }
  function onClickPage(event) {
    refetch({ search: myKeyWord, page: Number(event.target.id) });
  }
  return (
    <>
      <div>검색 페이지!!!</div>
      검색어 : <input type="text" onChange={onChangeSearch} />{" "}
      <button onClick={onClickSearch}>검색</button>
      {data?.fetchBoards.map((el) => (
        <div key={el._id}>
          <Column>{el.writer}</Column>
          <Column>{el.title}</Column>
          <Column>{el.createdAt}</Column>
        </div>
      ))}
      {new Array(10).fill(1).map((_, index) => (
        <Page key={uuidv4} onClick={onClickPage} id={String(index + 1)}>
          {index + 1}
        </Page>
      ))}
    </>
  );
}
検索機能を実現するためにはアイテムリストが必要なので、fetchBoardsを使用してインポートしたアイテムを配布します.
そしてonChangeとstate機能を利用して検索機能を実現する.
検索ウィンドウの一部でmySearchという名前のstateを使用して検索語をstateに配置します.
この値をmyKeywordという名前の値に入れ、mykeyword値を使用してrefetchを行います.
次に検索ボタンをクリックしてtitleと検索値が一致する部分を検索します.

Lodash Debounce
ボタンを押して検索することもできますが、検索語を入力する際に、その検索語を含む内容をそのまま表示する場合も多いです.
そのように検索機能を実現すると、問題が発生します.
検索語を入力するたびにサーバにリクエストを送信すると、大きなトラフィックの浪費を招く可能性があります.

Debounceは、繰り返し動作を強制的に待つ機能です.
応用する弾跳の完全なコード
import { useState } from "react";
import styled from "@emotion/styled";
import { useQuery, gql } from "@apollo/client";
import { v4 as uuidv4 } from "uuid";
import _ from "lodash";

const FETCH_BOARDS = gql`
  query fetchBoards($search: String, $page: Int) {
    fetchBoards(search: $search, page: $page) {
      _id
      writer
      title
      createdAt
    }
  }
`;
const Column = styled.span`
  padding: 0px 50px;
`;
const Page = styled.span`
  padding: 0px 10px;
  cursor: pointer;
`;
interface Iprops {
  isMatched: boolean;
}
const MyWord = styled.span`
  color: ${(props: Iprops) => (props.isMatched ? "red" : "black")};
`;
export default function SearchDebouncePage() {
  const { data, refetch } = useQuery(FETCH_BOARDS);

  //   const [mySearch, setMySearch] = useState();
  const [myKeyword, setMyKeyword] = useState();

  const getDebounce = _.debounce((data) => {
    refetch({ search: data, page: 1 });
    setMyKeyword(data);
  }, 500);
  function onChangeSearch(event) {
    // setMySearch(event.target.value);
    getDebounce(event.target.value);
  }
  //   function onClickSearch() {
  //     refetch({ search: mySearch, page: 1 });
  //     setMyKeyword(mySearch);
  //   }
  function onClickPage(event) {
    refetch({ search: myKeyword, page: Number(event.target.id) });
  }
  return (
    <>
      <div>검색어 입력</div>
      검색하기 : <input type="text" onChange={onChangeSearch} />{" "}
      {/* <button onClick={onClickSearch}>검색</button> */}
      {data?.fetchBoards.map((el) => (
        <div key={el._id}>
          <Column>{el.writer}</Column>
          <Column>
            {el.title
              .replaceAll(myKeyword, `#$#${myKeyword}#$#`)
              .split("#$#")
              .map((el) => (
                <MyWord key={uuidv4()} isMatched={myKeyword === el}>
                  {el}
                </MyWord>
              ))}
          </Column>
          <Column>{el.createdAt}</Column>
        </div>
      ))}
      {new Array(10).fill(1).map((_, index) => (
        <Page key={uuidv4} onClick={onClickPage} id={String(index + 1)}>
          {index + 1}
        </Page>
      ))}
    </>
  );
}
Deboring機能を使用するには、まずlodashをインポートします.
import _ from "lodash";
lodashをインポートした後.作成すると、使用可能なすべての機能が表示されます.

getDeboringという変数を作成し、リフレッシュします.
const getDebounce = _.debounce((data) => {
    refetch({ search: data, page: 1 });
    setMyKeyword(data);
  }, 500);
、500と書かれた部分が時間であり、それに対応する時間の追加入力がない場合は、サーバにステータス値を要求します.
これにより、検索ウィンドウで検索するたびに要求を送信するのではなく、入力を停止してから一定時間後に要求を送信するのではなく、サーバにデータをより効率的に要求できます.