๐Ÿ“– TIL - ๋‚˜์˜ ์ฒซ Custom Hook ๋„ˆ๋กœ ์ •ํ–ˆ๋‹ค.. ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€ : ์ƒํƒœ ๊ด€๋ฆฌ์˜ ์ •์„๊ณผ ๊ทธ ๊ณผ์ •

์Š˜ยท2025๋…„ 2์›” 6์ผ

๐Ÿ“– TIL

๋ชฉ๋ก ๋ณด๊ธฐ
48/89

โœจ Custom Hook ๊ฐœ์„  ๊ณผ์ •

1. ์ฒ˜์Œ ์ž‘์„ฑํ•œ Hook (์ž˜๋ชป๋œ ๋ฒ„์ „)

const useLocalStorage = (initialState) => {
  const getLocalStorage = (key) => {
    try {
      const item = window.localStorage.getItem(key);
      return item ? JSON.parse(item) : initialState;
    } catch (error) {
      console.error(error);
    }
  };
  
  const setLocalStorage = (key, data) => {
    try {
      if ((key, data)) window.localStorage.setItem(key, JSON.stringify(data));
    } catch (error) {
      console.error(error);
    }
  };
  
  return [getLocalStorage, setLocalStorage];
};

2. ๊ฐœ์„ ๋œ Hook (์˜ฌ๋ฐ”๋ฅธ ๋ฒ„์ „)

const useLocalStorage = (key, initialState) => {
  const [localStg, setLocalStg] = useState(() => {
    try {
      const item = window.localStorage.getItem(key);
      return item ? JSON.parse(item) : initialState;
    } catch (error) {
      console.error(error);
      return initialState;
    }
  });

  useEffect(() => {
    if (localStg !== undefined)
      window.localStorage.setItem(key, JSON.stringify(localStg));
  }, [key, localStg]);

  return [localStg, setLocalStg];
};

๐Ÿ” ๋ฌธ์ œ ๋ฐœ๊ฒฌ๊ณผ ํ•ด๊ฒฐ ๊ณผ์ •

1. ์ฒซ ์‹œ๋„: Add ๋กœ์ง์—์„œ ์ง์ ‘ localStorage ์„ค์ •

const addHandler = (e) => {
  e.stopPropagation();
  if (selectedPokemon.some((e) => e.id === pokemon.id)) {
    return toast.warn("๊ฐ™์€ ํฌ์ผ“๋ชฌ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.๐Ÿ‘€");
  }
  if (selectedIdx >= 6) {
    return toast.error("๋” ์ด์ƒ ์„ ํƒํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.๐Ÿ˜“");
  }
  dispatch(addPokemon({ ...pokemon }));
  setLocalStg(selectedPokemon)  // โŒ ๋ฌธ์ œ ๋ฐœ์ƒ!
  toast.success(`์•„์‹ธ!! "${pokemon.korean_name}"์„(๋ฅผ) ์žก์•˜๋‹ค!๐Ÿ’ช`);
};

2. ๋ฐœ๊ฒฌํ•œ ๋ฌธ์ œ์ 

  • useState์˜ ๋น„๋™๊ธฐ์  ํŠน์„ฑ์œผ๋กœ ์ธํ•ด ์ฆ‰์‹œ ๊ฐ’์ด ๋ฐ˜์˜๋˜์ง€ ์•Š์Œ
  • localStorage์— ๊ธฐ๋ณธ๊ฐ’๋งŒ ์ €์žฅ๋˜๊ณ  ์‹ค์ œ ๋ฐ์ดํ„ฐ๋Š” ์ €์žฅ๋˜์ง€ ์•Š์Œ

3. ์ตœ์ข… ํ•ด๊ฒฐ์ฑ…

const [, setLocalStg] = useLocalStorage('selectedPokemon', []);

useEffect(() => {
  setLocalStg(selectedPokemon)
}, [selectedPokemon, setLocalStg])

๐Ÿ’ก ํŠœํ„ฐ๋‹˜๊ณผ์˜ ๋ฉด๋‹ด์—์„œ ์–ป์€ ์ธ์‚ฌ์ดํŠธ

1. ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€ ๊ด€๋ฆฌ ๋ฐฉ์‹

  • Q: "๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€๋ฅผ ํ›…์œผ๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒŒ ์ผ๋ฐ˜์ ์ธ๊ฐ€์š”?"
  • A: "๋„ค, ๋งค์šฐ ์ผ๋ฐ˜์ ์ธ ํŒจํ„ด์ž…๋‹ˆ๋‹ค."
    • ๋ฆฌ๋“€์„œ๋Š” ์ˆœ์ˆ˜ ํ•จ์ˆ˜์—ฌ์•ผ ํ•˜๋ฏ€๋กœ ๋ธŒ๋ผ์šฐ์ € API ํ˜ธ์ถœ์ด ์–ด๋ ค์›€
    • ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ(useEffect ๋“ฑ)๋Š” ์ปค์Šคํ…€ ํ›…์—์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Œ

2. Custom Hook vs Redux

  • Q: ๋ฆฌ๋•์Šค๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์ปค์Šคํ…€ ํ›…์€ ์–ธ์ œ ํ™œ์šฉํ•˜๋Š” ๊ฒŒ ์ข‹์„๊นŒ์š”?
  • A: ์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ๊ฐ€ ํ•„์š” ์—†์„ ๋•Œ
    โ†’ ์ฆ‰, ํŠน์ • ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ๋งŒ ํ•„์š”ํ•œ ์ƒํƒœ๋ผ๋ฉด ๊ตณ์ด ๋ฆฌ๋•์Šค๋ฅผ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์—†์Œ.
    • Custom Hook ์‚ฌ์šฉ ์ผ€์ด์Šค:
      • ๋ธŒ๋ผ์šฐ์ € API ์—ฐ๋™
      • ์ปดํฌ๋„ŒํŠธ ํŠนํ™” ๋กœ์ง
      • ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋กœ์ง
    • Redux ์‚ฌ์šฉ ์ผ€์ด์Šค:
      • ๋ณต์žกํ•œ ์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ
      • ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ์ƒํƒœ ํ๋ฆ„ ํ•„์š” ์‹œ
      • ๋Œ€๊ทœ๋ชจ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜

3. ํ˜„๋Œ€์˜ ์ƒํƒœ ๊ด€๋ฆฌ ํŠธ๋ Œ๋“œ

  • Q: "ํ˜น์‹œ ๊ทธ๋Ÿฌ๋ฉด.. ์‹ค๋ฌด์—์„œ ๋งŽ์ด ์„ ํ˜ธํ•˜์‹œ๋Š” ์ƒํƒœ๊ด€๋ฆฌ๋Š” ์–ด๋–ค๊ฑด๊ฐ€์š”?"
  • A: "์‹ ๊ทœ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค๋•Œ๋Š” ๋ฆฌ๋•์Šค๋ฅผ ์ž˜ ์•ˆ์“ฐ๋Š” ์ถ”์„ธ์ž…๋‹ˆ๋‹ค. ๋Œ€์ฒด ๊ธฐ์ˆ ๋กœ Zustand๋กœ ๋งŽ์ด ์“ฐ์ด๋Š”๊ฒƒ ๊ฐ™์•„์š”"
    • ๋ฆฌ๋•์Šค์˜ ์‚ฌ์šฉ ๋นˆ๋„๊ฐ€ ์ค„์–ด๋“œ๋Š” ์ถ”์„ธ
    • ์ƒˆ๋กœ์šด ๋Œ€์•ˆ๋“ค์ด ๋ถ€์ƒ
      • React Query: ์„œ๋ฒ„ ์ƒํƒœ ๊ด€๋ฆฌ
      • Zustand: ๊ฐ„๋‹จํ•œ ํด๋ผ์ด์–ธํŠธ ์ƒํƒœ ๊ด€๋ฆฌ
    • "ํ•„์š”ํ•œ ๋งŒํผ๋งŒ" ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ํŠธ๋ Œ๋“œ

๐ŸŽฏ ์‹ค๋ฌด์  Best Practice

  1. ์ƒํƒœ ๊ด€๋ฆฌ ๋„๊ตฌ ์„ ํƒ ๊ธฐ์ค€

    • ํ”„๋กœ์ ํŠธ ๊ทœ๋ชจ
    • ํŒ€์˜ ์นœ์ˆ™๋„
    • ์œ ์ง€๋ณด์ˆ˜ ์šฉ์ด์„ฑ
  2. ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€ ๊ด€๋ฆฌ

    • Custom Hook์œผ๋กœ ๋ถ„๋ฆฌ
    • useEffect๋กœ ๋™๊ธฐํ™”
    • ์—๋Ÿฌ ์ฒ˜๋ฆฌ ํฌํ•จ
  3. ์ฝ”๋“œ ๊ตฌ์กฐํ™”

    • ๊ด€์‹ฌ์‚ฌ ๋ถ„๋ฆฌ
    • ์žฌ์‚ฌ์šฉ์„ฑ ๊ณ ๋ ค
    • ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ

โญ๏ธ ํ•ต์‹ฌ ๋ฐฐ์šด ์ 

  1. Custom Hook์œผ๋กœ ๋ธŒ๋ผ์šฐ์ € API ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ๋ฒ ์ŠคํŠธ ํ”„๋ž™ํ‹ฐ์Šค
  2. useState์˜ ๋น„๋™๊ธฐ์  ํŠน์„ฑ ์ดํ•ด์˜ ์ค‘์š”์„ฑ
  3. useEffect๋ฅผ ํ†ตํ•œ ์ ์ ˆํ•œ ๋™๊ธฐํ™”์˜ ํ•„์š”์„ฑ
  4. ํ˜„๋Œ€ ์›น ๊ฐœ๋ฐœ์—์„œ์˜ ์ƒํƒœ ๊ด€๋ฆฌ ํŠธ๋ Œ๋“œ ๋ณ€ํ™”

๐Ÿš€ ์•ž์œผ๋กœ์˜ ํ•™์Šต ๋ฐฉํ–ฅ

  • React Query, Zustand ๋“ฑ ๋ชจ๋˜ ์ƒํƒœ ๊ด€๋ฆฌ ๋„๊ตฌ ํ•™์Šต
  • Custom Hook ๋””์ž์ธ ํŒจํ„ด ์‹ฌํ™” ํ•™์Šต
profile
์ฃผ๋‹ˆ์–ด ํ”„๋ก ํŠธ์—”๋“œ ์„ฑ์žฅ๊ธฐ ๊ธฐ๋ก๊ธฐ๋ก

0๊ฐœ์˜ ๋Œ“๊ธ€