3. React Hooks

  • React Hook ์ด๋ž€

  • Hooks

    • useState

    • useEffect

    • useContext

    • useRef

    • useLayoutEffect

  • React StrictMode ๋ž€

๊ฐ•์˜ ์ •๋ฆฌ

React์˜ Hook

(์‚ฌ์†Œํ•จ) ๋ณดํ†ต ์™ธ๊ตญ์—์„œ๋Š” ๋ณต์ˆ˜ํ˜•์œผ๋กœ ๋งŽ์ด ๋ถ€๋ฅธ๋‹ค. Hooks, Github Actions. ํ•œ๊ตญ์—์„œ๋Š” Hook, Github Action๊ณผ ๊ฐ™์ด ๋‹จ์ˆ˜๋กœ ๋งŽ์ด ํ‘œ๊ธฐํ•œ๋‹ค.

React 16๋ถ€ํ„ฐ ์ฒด๊ณ„๊ฐ€ ์žกํ˜”๋‹ค. React 16.8์—์„œ Hooks๊ฐ€ ๋„์ž…๋˜์—ˆ๋‹ค. React 18์—์„œ๋Š” Concurrent Mode๊ฐ€ ๊ฐ•์กฐ๊ฐ€ ๋˜์—ˆ๋‹ค.

๋ฆฌ์•กํŠธ์—์„œ ์‚ฌ์šฉํ•˜๋˜ ๊ธฐ์กด ๋ฐฉ์‹์˜ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๋‹ค.

  • Wrapper Hell (HoC), ์žฅํ’์„ ์˜๊ฒŒ ๋œ๋‹ค.

  • Huge Components

  • Confusing Classes, ๋‚œํ•ดํ•œ this

Class Component๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ, ๊ฐ์ฒด์ง€ํ–ฅ์œผ๋กœ ์งœ๋Š”๊ฒƒ๋„ ์•„๋‹ˆ๋‹ค. ํ˜ผ๋ž€์Šค๋Ÿฌ์šด ๋ฉด์ด ์žˆ์—ˆ๋‹ค. Class Component๋ฅผ ์—†์• ๊ฒ ๋‹ค๋Š” ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ, Function Component์™€ Hook์„ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋ผ๋Š” ๋ง. ๊ธฐ์กด์˜ Class ์ฝ”๋“œ๋Š” ๋ฌธ์ œ์—†์ด ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

์˜ˆ์ „์—๋Š” ์ƒํƒœ๋ฅผ ๊ฐ€์ง„ ์ปดํฌ๋„ŒํŠธ๋ฅผ Class Component๋กœ ๋งŒ๋“ค๊ณ  props๋งŒ ์žฌ์‚ฌ์šฉ ํ•˜๋Š” ์ˆœ์ˆ˜ํ•œ ์ปดํฌ๋„ŒํŠธ๋Š” Function Component๋กœ ์ž‘์„ฑํ–ˆ๋‹ค. Redux์—์„œ๋Š” Presentational, Container Components๋กœ ๋ถ„๋ฆฌํ–ˆ๋‹ค.

์ด์ œ๋Š” ๋ชจ๋‘ Function Component๋กœ ์‚ฌ์šฉํ•œ๋‹ค. ๋„๋ฉ”์ธ ๋กœ์ง๋“ค์„ ๋ชจ๋‘ ์ปค์Šคํ…€ ํ›…์œผ๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ์žฌ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

๋Œ€ํ‘œ์ ์ธ Hooks

  • useState -> State Hook -> React์˜ State

  • useEffect -> Side-effect

  • useContext

  • useRef

  • useLayoutEffect -> useEffect์™€ ๊ฐ™๊ฒŒ ๋™์ž‘ํ•˜์ง€๋งŒ ์‹คํ–‰ ์‹œ์ ์ด ๋‹ค๋ฅด๋‹ค.

useEffect

๋ฆฌ์•กํŠธ ๋ฒ ํƒ€ ๋ฌธ์„œ์— You Might Not Need an Effect๋ผ๋Š” ์ฃผ์ œ์˜ ๋‚ด์šฉ๋„ ์žˆ๋“ฏ์ด useEffect๋ฅผ ์ œ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ ์ค‘์š”ํ•˜๋‹ค. useEffect๋Š” ๋ Œ๋”๋ง ์ดํ›„์— ํ•ด์•ผ ํ•  ์ผ, React์˜ ์™ธ๋ถ€์™€ ๊ด€๋ จ๋œ ์ผ์„ ์ •ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

ํƒ€์ด๋จธ ์˜ˆ์ œ

// ๋ธŒ๋ผ์šฐ์ €์˜ title์„ ๋ฐ€๋ฆฌ์ดˆ๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค.
useEffect(() => {
  document.title = `Now: ${new Date().getTime()}`;
});
function Timer() {
  useEffect(() => {
    const savedTitle = document.title;
    // useEffect ๋‚ด๋ถ€์—์„œ setTimeout, setInterval์„ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ์—๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ unmount ๋˜์—ˆ์„ ๋•Œ clear๋ฅผ ํ•ด์ค˜์•ผ ํ•œ๋‹ค.
    // useEffect์˜ clean up ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด์„œ ์ฒ˜๋ฆฌํ•œ๋‹ค.
    const id = setInterval(() => {
      document.title = `Now: ${new Date().getTime()}`;
    }, 100);

    return () => {
      document.title = savedTitle;
      clearInterval(id);
    };
  });

  return <p>Playing</p>;
}

export default function TimerControl() {
  const [playing, setPlaying] = useState(false);

  const handleClick = () => {
    setPlaying(!playing);
  };

  return (
    <div>
      {playing ? <Timer /> : <p>Stop</p>}
      <button type="button" onClick={handleClick}>
        Toggle
      </button>
    </div>
  );
}

์ฒ˜์Œ์— ํ•œ๋ฒˆ๋งŒ ์‹คํ–‰ํ•˜๊ธฐ

useEffect์˜ 2๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜์— ์˜์กด์„ฑ ๋ฐฐ์—ด์„ ๋„ฃ์–ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

  • ๋นˆ ๋ฐฐ์—ด์„ ๋„ฃ์œผ๋ฉด, ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ฒ˜์Œ mount๋  ๋•Œ๋งŒ useEffect์˜ setup function์ด ์‹คํ–‰๋œ๋‹ค.

  • ํŠน์ • ๊ฐ’์„ ๋‹ด๊ณ  ์žˆ๋Š” ๋ฐฐ์—ด์„ ๋„ฃ์œผ๋ฉด, ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ฒ˜์Œ mount๋  ๋•Œ์™€, ํŠน์ • ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ๋งŒ useEffect์˜ setup function์ด ์‹คํ–‰๋œ๋‹ค.

  • ๋ฐฐ์—ด์„ ๋„ฃ์–ด์ฃผ์ง€ ์•Š์œผ๋ฉด, ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ฒ˜์Œ mount๋  ๋•Œ์™€, ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง์ด ๋  ๋•Œ๋งˆ๋‹ค setup function์ด ์‹คํ–‰๋œ๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ๋Š” data fetching์„ ํ•  ๋•Œ useEffect๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

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

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

  fetchProducts();
}, []);

fetchProducts๋ผ๋Š” ํ•จ์ˆ˜๊ฐ€ useEffect ๋‚ด๋ถ€์— ์žˆ์–ด์•ผ ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ์˜๋ฌธ์ด ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค. ์‹ค์ œ๋กœ useEffect ์™ธ๋ถ€์—, ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์— ์„ ์–ธํ•ด๋„ ๋ฌธ์ œ๋Š” ์—†๋‹ค. ํ•˜์ง€๋งŒ fetchProducts ๋‚ด๋ถ€์—์„œ Component์˜ State๊ฐ’์„ ์ฐธ์กฐํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ๋‹ค. Component๊ฐ€ ๋ Œ๋”๋ง์ด ๋˜์—ˆ์„ ๋•Œ ๋ฐ”๊นฅ์— ์žˆ๋Š” ๋ณ€์ˆ˜๋“ค์„ ์บก์ฒ˜ํ•ด์„œ ์“ฐ๊ธฐ ๋•Œ๋ฌธ์—(๋ฐ”์ธ๋”ฉ) ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ๋‹ค. ๊ฐ€๋Šฅํ•˜๋ฉด ํ•จ์ˆ˜๋“ค์„ useEffect ๋‚ด๋ถ€์— ๋ชจ๋‘ ๋„ฃ์œผ๋ฉด ๊ณ ๋ฏผํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค. useEffect์˜ setup function์ด ํด๋กœ์ €๊ฐ€ ๋œ๋‹ค.

Effect๊ฐ€ ๋‘ ๋ฒˆ ์‹คํ–‰๋˜๋Š” ๋ฌธ์ œ

StrictMode๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ๋ฅผ ๊ฒ€์‚ฌํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค. dev ํ™˜๊ฒฝ์—์„œ ๋ Œ๋”๋ง์ด 2๋ฒˆ ๋˜๋Š”๊ฒƒ์€ ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ๋‹ค. ๊ฐ„ํ˜น useEffect์—์„œ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋Š”๋ฐ, flag ๋ณ€์ˆ˜๋ฅผ ์ด์šฉํ•œ๋‹ค.

์˜์กด์„ฑ ๋ฐฐ์—ด์„ ์ด์šฉํ•ด Fetchํ•  ๋•Œ ์ฃผ์˜์‚ฌํ•ญ

๋ฆฌ์•กํŠธ์—์„œ๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ unmount ๋˜์—ˆ์„ ๋•Œ ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธ ํ•˜๋ ค๊ณ  ํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธด๋‹ค. ์ด๋ฅผ ๋ง‰๊ธฐ์œ„ํ•ด flag ๋ณ€์ˆ˜๋ฅผ ์ด์šฉํ•˜์—ฌ data fetching์ด ์™„๋ฃŒ๋˜์—ˆ์„ ๋•Œ ์ปดํฌ๋„ŒํŠธ๊ฐ€ unmount๋˜์ง€ ์•Š์•˜์œผ๋ฉด setter function์„ ์‹คํ–‰ํ•˜๋„๋ก ํ•œ๋‹ค. axios๋ฅผ ์ด์šฉํ•˜๋Š” ๊ฒฝ์šฐ์— ๊ธฐ์กด์—๋Š” cancelToken์„ ์‚ฌ์šฉํ–ˆ๋Š”๋ฐ ์ด์ œ๋Š” deprecated ๋˜์—ˆ๊ณ  AbortController๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๊ฒƒ์ด ๊ถŒ์žฅ๋œ๋‹ค.

Last updated