[React] useDebounce 커스텀 훅 간단 맛보기

이크·2024년 9월 12일
0

react

목록 보기
5/5

Debounce?

Debounce란 Debouncing is a technique in programming that helps improve the performance of web applications by controlling the frequency at which time-consuming tasks are triggered. 라고 적혀있다. 간단하게 말하면, 트리거가 계속 발동되어 성능 저하가 되는 것을 막기 위한 기술이다.

코드 작성

https://velog.io/@ekrtionl/React-loader-action-2-json

위 내용에서 이어서 작업했다.

먼저 useDebounce 훅을 작성했다. 검색 값과 delay 시간을 파라미터로 받아 이를 찾는 훅을 만들었다.

// useDebounce.js

import { useEffect, useState } from "react";

const useDebounce = (value, delay) => {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => {
      clearTimeout(handler);
    };
  }, [value, delay]);

  return debouncedValue;
};

export default useDebounce;

사실 debounce에서 delay 시간만큼 기다렸다가 데이터를 fetch 후 해당 데이터를 넘기는 코드를 작성하는 것이 일반적인 것 같다. 하지만 내가 기존에 작성한 코드는 전체 데이터를 가져오기 때문에, 이후 input 창에 값을 입력하면 해당하는 데이터들을 filtering 하는 식으로 코드를 간단하게 작성했다.

// ArticlePage.jsx

import { useQuery } from "@tanstack/react-query";
import { useState } from "react";
import { Link, json, defer } from "react-router-dom";
import useDebounce from "../utils/useDebounce";

function ArticlesPage() {
  const { data, isPending, isError, error } = useQuery({
    queryKey: ["articles"],
    queryFn: () =>
      fetch("https://jsonplaceholder.typicode.com/posts").then((res) =>
        res.json()
      ),
  });

  const [searchTerm, setSearchTerm] = useState("");
  const debounceSearchTerm = useDebounce(searchTerm, 500);

  let content;

  if (isPending) {
    content = <p>Loading!!!</p>;
  }
  if (isError) {
    content = <p>error : {error.message}</p>;
  }

  if (data) {
    const filteredData = data.filter((article) =>
      article.title.toLowerCase().includes(debounceSearchTerm.toLowerCase())
    );

    content = (
      <ol>
        {filteredData.map((article) => (
          <li key={article.id}>
            <Link to={`${article.id}`}>{article.title}</Link>
          </li>
        ))}
      </ol>
    );

    // content = (
    //   <ol>
    //     {data.map((article) => (
    //       <li key={article.id}>
    //         <Link to={`${article.id}`}>{article.title}</Link>
    //       </li>
    //     ))}
    //   </ol>
    // );
  }
  return (
    <div>
      <Link to={"new"}>New</Link>
      <p>ArticlesPage</p>
      <input
        type='text'
        placeholder='input'
        onChange={(e) => setSearchTerm(e.target.value)}
      />
      {content}
    </div>
  );
}

export default ArticlesPage;

async function loadArticles() {
  const response = await fetch("https://jsonplaceholder.typicode.com/posts");
  console.log(response);

  if (response.status !== 200) {
    return json({ message: "POST 불러오기 실패" }, { status: 500 });
  } else {
    const resData = await response.json();
    return resData;
  }
}

export function loader() {
  return defer({
    articles: loadArticles(),
  });
}

지금은 jsonplaceholder를 사용해서 간단한 API를 썼지만, 이후에는 직접 API를 만들어 더 좋은 코드를 작성할 예정이다.

profile
공부 기록 일기. 까먹지 않기 위해

0개의 댓글