Custom Hook

ํ•™์Šต ํ‚ค์›Œ๋“œ

  • Custom Hook

    • Hook์˜ ๊ทœ์น™

  • usehooks-ts

    • useBoolean

    • useCounter

    • useEffectOnce

    • useFetch

      • SWR

      • React-Query

    • useInterval

    • useEventListener

    • useLocalStorage

    • useDarkMode

๐Ÿ“– Custom Hook

  • ์ปดํฌ๋„ŒํŠธ ๋กœ์ง์„ ํ•จ์ˆ˜๋กœ ๋ฝ‘์•„๋‚ด์–ด ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•

  • React์˜ State์™€ Lifecycle ๊ด€๋ฆฌ ๋กœ์ง์„ ๊ณตํ†ตํ™” ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ์—ญํ™œ (์ปดํฌ๋„ŒํŠธ๊ฐ„์˜ ๋กœ์ง ๊ณต์œ )

๐Ÿค– Custom hook ์‚ฌ์šฉ๋ฒ•

  • use๋กœ ์‹œ์ž‘ํ•ด์•ผ ํ•˜๊ณ  PascalCase๋กœ ์ด๋ฆ„์„ ์ƒ์„ฑํ•œ๋‹ค.

  • ๐Ÿ“ hooksํด๋”๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ํ•˜๋‚˜์˜ ํŒŒ์ผ๋กœ ๋ถ„๋ฆฌ ํ›„ ์‚ฌ์šฉ

๐Ÿ“Œ Hook์˜ ๊ทœ์น™

1. ์ตœ์ƒ์œ„(at the Top Level)์—์„œ๋งŒ Hook์„ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค

  • ๋ฐ˜๋ณต๋ฌธ, ์กฐ๊ฑด๋ฌธ ํ˜น์€ ์ค‘์ฒฉ๋œ ํ•จ์ˆ˜ ๋‚ด์—์„œ Hook์„ ํ˜ธ์ถœํ•˜์ง€ ์•Š๋Š”๋‹ค.

// ์ฒ˜์Œ์—๋Š” ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋‚˜ ์กฐ๊ฑด๋ฌธ ์•ˆ์—์„œ Hook์„ ํ˜ธ์ถœํ•˜๋Š” ์‹ค์ˆ˜๋ฅผ ํ•˜๊ฒŒ ๋œ๋‹ค.
// Bad!!
if (playing) {
 const products = useFetchProducts();
 console.log(products);
}

2. React ํ•จ์ˆ˜ ๋‚ด์—์„œ Hook์„ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค

  • React ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์—์„œ Hook์„ ํ˜ธ์ถœ

  • Custom Hook์—์„œ Hook์„ ํ˜ธ์ถœ

๐Ÿ“– usehooks-ts๋ž€?

  • Hook ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

  • Hook์„ ์–ด๋–ป๊ฒŒ ๋งŒ๋“ค์—ˆ๋Š”์ง€ ์ฝ”๋“œ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๊ณ  Custom Hook์„ ๋งŒ๋“œ๋Š”๋ฐ ์˜๊ฐ์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

usehooks-ts ์„ค์น˜

npm i usehooks-ts

โš™๏ธ useBoolean

  • ์ฐธ/๊ฑฐ์ง“์„ ๋‹ค๋ฃฐ ๋• toggle ๊ฐ™์ด ์˜๋„๊ฐ€ ๋ช…ํ™•ํ•œ ํ•จ์ˆ˜๋ฅผ ์“ฐ๋Š” ๊ฒŒ ์ข‹๋‹ค.

import { useState } from 'react';
import { useBoolean } from 'usehooks-ts';

export default function Toggle() {

  const [stateToggle, setStateToggle] = useState(false);
  const { value: myToggle, toggle: myToggleFun } = useBoolean(false); 
  // setStateToggle(!stateToggle) ๋ณด๋‹ค toggle ํ˜น์€ myToggleFun์ด ์˜๋„๊ฐ€ ๋ช…ํ™•ํ•˜๋‹ค.

  const handleState = () => {
    setStateToggle(!stateToggle); 
  };

  return (
    <div>
      <p> useState : {stateToggle ? 'True' : 'False'}</p>
      <p> useBoolean : {myToggle ? 'True' : 'False'}</p>
      <button type="button" onClick={handleState}>
        useState hook ํ† ๊ธ€ ๋ฒ„ํŠผ
      </button>
      <button type="button" onClick={myToggleFun}>
        useBoolean hook ํ† ๊ธ€ ๋ฒ„ํŠผ
      </button>
    </div>
  );
}

โš™๏ธ useCounter

import { useCounter } from 'usehooks-ts'; // ์‚ฌ์šฉํ•ด๋ณด๋‹ˆ,ํ›จ์”ฌ ์ฝ”๋“œ์˜ ์˜๋„๊ฐ€ ๋ช…ํ™•ํ•ด์ง€๊ณ  ๊ฐ„๊ฒฐํ•˜๋‹ค. 

export default function Toggle() {
  const { count, increment } = useCounter(0);

  return (
    <div>
      <p> useCounter : {count}</p>
      <button type="button" onClick={increment}> 
        useCounter hook ๋ฒ„ํŠผ
      </button>
    </div>
  );
}

โš™๏ธ useEffectOnce

  • ์˜์กด์„ฑ ๋ฐฐ์—ด์„ ๋นˆ ๋ฐฐ์—ด๋กœ ๋„ฃ์–ด์„œ ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰ํ•˜๋Š” Effect๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์€๋ฐ useEffectOnce hook ์ด๋ฆ„์—์„œ๋ถ€ํ„ฐ ์˜๋„๊ฐ€ ๋ช…ํ™•ํžˆ ๋“œ๋Ÿฌ๋‚œ๋‹ค.

const [products, setProducts] = useState<Product[]>([]);

useEffectOnce(() => {
  const fetchProducts = async () => {
  const url = 'http://localhost:3000/products';
  const response = await fetch(url);
  const data = await response.json();
  setProducts(data.products);
 };

 fetchProducts();
});

return products;

โš™๏ธ useFetch

  • ์ •๋ง ๊ฐ„๋‹จํžˆ ์“ธ ๋•Œ ์ข‹์Œ, ๊ทธ๋Ÿฌ๋‚˜ ๊ธฐ๋Šฅ์ด ๋งŽ์ง€ ์•Š๋‹ค.

export default function useFetchProducts() {
  const url = 'http://localhost:3000/products';
  const { data } = useFetch(url);
  if (!data) { 
    return []; 
  }
  return data.products;
}
  • ๋ช‡ ๊ฐ€์ง€ ๊ธฐ๋Šฅ์ด ์‚ด์ง ๋” ์žˆ๋Š” useFetch ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋”ฐ๋กœ ์žˆ๋‹ค. โ†’ use-http (๋งŽ์ด ์‚ฌ์šฉํ•˜์ง„ ์•Š๋Š”๋‹ค.)

  • ์‚ฌ์šฉ๋ฒ•์ด ๋” ๋ณต์žกํ—ค๋„ ๊ดœ์ฐฎ๋‹ค๋ฉด, ์บ์‹œ ์ด์Šˆ๋ฅผ ๊ณ ๋ คํ•˜๋Š” ๋‹ค๋ฅธ ๋Œ€์•ˆ์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์žˆ๋‹ค.

    • SWR : ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ๋ฅผ ์œ„ํ•œ React Hooks

SWR์„ ์‚ฌ์šฉํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ๋Š” ์ฃผ๊ธฐ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฐ”๋€Œ์—ˆ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๊ฒŒ์‹œํŒ์ด๋ฉด ๊ฒŒ์‹œ๋ฌผ์ด ์˜ฌ๋ผ์™”๋Š”์ง€ ํ™•์ธํ•œ๋‹ค. React Query๋Š” ์ด๋ณด๋‹ค ๋” ๋ณต์žกํ•œ ๊ฒƒ์„ ๋‹ค๋ฃฐ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

โš™๏ธ useInterval

โš™๏ธ useEventListener

  • โญ๏ธ ๊ฐ•๋ ฅ ์ถ”์ฒœ โญ๏ธ

  • ๋ชจ๋“  ์ข…๋ฅ˜์˜ ์ด๋ฒคํŠธ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ํŠนํžˆ dispatchEvent๋กœ ์ „๋‹ฌ๋˜๋Š” ์ปค์Šคํ…€ ์ด๋ฒคํŠธ์— ๋ฐ˜์‘ํ•˜๊ธฐ ์ข‹๋‹ค.

โš™๏ธ useLocalStorage

  • LocalStorage์— ๊ฐ์ฒด๋ฅผ ๋„ฃ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค. ์ด์™€ ๊ฐ™์€ ๊ฒฝ์šฐ stringfy ์™€ parse๋ฅผ ์ž๋™์œผ๋กœ ํ•ด์ค€๋‹ค.

  • ์ด๋ฒคํŠธ๋ฅผ ํ†ตํ•ด(dispatchEvent + useEventListener) ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์™€ ๋™๊ธฐํ™”ํ•˜๋Š” ๊ฒŒ ๋งค์šฐ ์ค‘์š”ํ•œ ํŠน์ง•

โš™๏ธ useDarkMode

  • os ์šด์˜์ฒด์ œ์˜ ๋‹คํฌํ…Œ๋งˆ๋ฅผ ํ™œ์šฉํ•˜๊ณ  ์‹ถ์„ ๋•Œ

โœ๐Ÿป Custom Hook, usehooks-ts ์ •๋ฆฌ

  • Custom Hook์„ ํ™œ์šฉํ•œ๋‹ค๋ฉด ์žฌ์‚ฌ์šฉ ์ธก๋ฉด์—์„œ ๋ฆฌ์•กํŠธ์˜ ๊ฐ•์ ์„ ์ œ๋Œ€๋กœ ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์žฌ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋กœ์ง์„ ์ž˜ ์ƒ๊ฐํ•ด์•ผ ํ•  ๊ฒƒ ๊ฐ™๋‹ค.

  • usehooks-ts ์ฐธ๊ณ  ํ• ๋งŒ ํ•œ ๋‚ด์šฉ์ด ๋งŽ๊ณ , ํ™œ์šฉ์„ฑ ์ธก๋ฉด ์•ผ์‚ด๋‹˜์€ ์ถ”์ฒœํ•œ๋‹ค.

  • ๋ณ„๋„ ์„ค์น˜ ์—†์ด ์ฝ”๋“œ๋ฅผ ๋ณต์‚ฌํ•ด์„œ ์‚ฌ์šฉํ•ด๋„ ์ข‹๊ณ , Custom Hook์˜ ํ™œ์šฉ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ๋งŽ๊ธฐ ๋•Œ๋ฌธ์— ์ž์ฃผ ๋ณด๋ฉด์„œ ์˜๊ฐ์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ”— ์ฐธ๊ณ 

Last updated