๐Ÿ’ป์›น(Web)/React

[React]Custom Hook

stonesy 2024. 6. 28. 11:45
728x90

Custom Hook

Custom Hook์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ์— ์‚ฌ์šฉํ•˜๋ฉด ์ข‹๋‹ค๊ณ  ํ•œ๋‹ค.

  1. ์žฌ์‚ฌ์šฉ์„ฑ: ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋™์ผํ•œ ๋กœ์ง์„ ๋ฐ˜๋ณตํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ, Custom Hook์œผ๋กœ ๋ถ„๋ฆฌํ•˜๋ฉด ์ฝ”๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์šฉ์ดํ•˜๋‹ค.
  2. ์ปดํฌ๋„ŒํŠธ ๊ฐ€๋…์„ฑ ํ–ฅ์ƒ: ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์— ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ๋งŽ์•„์ง€๋ฉด ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์งˆ ์ˆ˜ ์žˆ๋‹ค. Custom Hook์œผ๋กœ ๋กœ์ง์„ ๋ถ„๋ฆฌํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋” ๊น”๋”ํ•˜๊ณ  ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์›Œ์ง„๋‹ค.
  3. ๋‹จ์ผ ์ฑ…์ž„ ์›์น™: ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ•œ๊ฐ€์ง€ ์ฑ…์ž„๋งŒ ๊ฐ€์ง€๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด Custom Hook์„ ์‚ฌ์šฉํ•ด ๋กœ์ง์„ ๋ถ„๋ฆฌํ•˜๋ฉด ์ข‹๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๊ฐ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ช…ํ™•ํ•œ ์—ญํ• ์„ ๊ฐ€์ง€๊ฒŒ ๋˜์–ด ์ฝ”๋“œ์˜ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์‰ฌ์›Œ์ง„๋‹ค.
  4. ์ƒํƒœ ๊ด€๋ฆฌ์™€ ๋ถ€์ˆ˜ ํšจ๊ณผ ์ฒ˜๋ฆฌ: ๋ณต์žกํ•œ ์ƒํƒœ ๊ด€๋ฆฌ๋‚˜ ๋ถ€์ˆ˜ ํšจ๊ณผ(side effects)๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ, Custom Hook์„ ์‚ฌ์šฉํ•˜๋ฉด ์ด ๋กœ์ง์„ ๊น”๋”ํ•˜๊ฒŒ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  5. ๊ณตํ†ต ํŒจํ„ด ๋ถ„๋ฆฌ: ํŠน์ •ํ•œ ํŒจํ„ด(์˜ˆ: ๋ฐ์ดํ„ฐ ํŽ˜์นญ, ํผ ํ•ธ๋“ค๋ง ๋“ฑ)์ด ๋ฐ˜๋ณต๋˜๋Š” ๊ฒฝ์šฐ, Custom Hook์œผ๋กœ ๋ถ„๋ฆฌํ•˜๋ฉด ์ด๋Ÿฌํ•œ ํŒจํ„ด์„ ํ•œ ๊ณณ์— ๋ชจ์•„ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

 

Custom Hook with axios

ํŠน์ •ํ•œ ํŒจํ„ด(์˜ˆ: ๋ฐ์ดํ„ฐ ํŽ˜์นญ, ํผ ํ•ธ๋“ค๋ง)์ด ๋ฐ˜๋ณต๋˜๋Š” ๊ฒฝ์šฐ Custom Hook์œผ๋กœ ๋ถ„๋ฆฌํ•˜๊ธฐ๋„ ํ•œ๋‹ค๊ณ  ํ–ˆ์œผ๋‹ˆ, axios๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์„ Custom Hook์œผ๋กœ ๋ถ„๋ฆฌํ•ด๋ณด์ž.

1. axios ์„ค์น˜

npm install axios

 

2. useAxios Custom Hook

import { useState, useEffect } from "react";
import axios from "axios";

function useAxios(url, params = {}) {
  const [loading, setLoading] = useState(true);
  const [data, setData] = useState([]);
  const [error, setError] = useState(null);

  useEffect(() => {
    setLoading(true);
    axios
      .get(url, { params })
      .then((res) => {
        setData(res.data.collection.items);
      })
      .catch((err) => {
        setError(err);
      })
      .finally(() => {
        setLoading(false);
      });
  }, [url, params]);

  return { loading, data, error };
}

export default useAxios;

 

3. using useAxios

GET ์š”์ฒญ

import PropTypes from "prop-types";
import useAxios from "../hook/useAxios";
import { useMemo } from "react";

GetData.propTypes = {
  query: PropTypes.string.isRequired,
};

function GetData({ query }) {
  const memoizedQuery = useMemo(() => ({ q: query }), [query]);
  const { loading, data, error } = useAxios("https://images-api.nasa.gov/search", memoizedQuery);

  if (loading) return <div><p>Loading...</p></div>;
  if (error) return <div><p>Error: {error.message}</p></div>;

  return (
    <div>
      <h1>NASA Astronomy Picture of the Day</h1>
      {data.map((item, index) => (
        <div key={index}>
          <h2>{item.data[0]?.title}</h2>
          <p>{item.data[0]?.date_created}</p>
          <img src={item.links ? item.links[0]?.href : ""} alt={item.data[0]?.title} />
          <p>{item.data[0]?.description}</p>
        </div>
      ))}
    </div>
  );
}

export default GetData;

 

 

 

⇒ useEffect์— ์˜์กด์„ฑ ๋ฐฐ์—ด์„ ๋„ฃ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ refetch๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

import { useState, useCallback } from "react";
import axios from "axios";

function useAxios(url, params = {}) {
  const [loading, setLoading] = useState(true);
  const [data, setData] = useState([]);
  const [error, setError] = useState(null);

  const fetchData = useCallback(() => {
    setLoading(true);
    axios
      .get(url, { params })
      .then((res) => {
        setData(res.data.collection.items);
      })
      .catch((err) => {
        setError(err);
      })
      .finally(() => {
        setLoading(false);
      });
  }, [url, params]);

  return { loading, data, error, refetch: fetchData };
}

export default useAxios;

 

์•„์ง^^.. ์ž˜ ๋ชจ๋ฅด๊ฒ ๋‹ค…

 

์ฐธ๊ณ 

21. ์ปค์Šคํ…€ Hooks ๋งŒ๋“ค๊ธฐ · GitBook

728x90