๐Ÿฅ ๊ณต์‹๋ฌธ์„œ๋กœ ๋ฐฐ์šฐ๋Š” React

Sohyeon Bakยท2022๋…„ 8์›” 26์ผ
0

React

๋ชฉ๋ก ๋ณด๊ธฐ
9/9
post-thumbnail

06. hook

hook์€ ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์•„๋‹Œ ๊ณณ์—์„œ state์™€ ๋ฆฌ์•กํŠธ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ค€๋‹ค.
state์™€ ์ƒ๋ช…์ฃผ๊ธฐ ๋ฉ”์„œ๋“œ๋ฅผ ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ ์ง€์†ํ•ด์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋„๋ก ๋งŒ๋“ค์–ด์ฃผ๊ณ  ๋ฆฌ์•กํŠธ์—์„œ ์ œ๊ณตํ•ด์ฃผ๊ณ  ์žˆ๋‹ค.

useState

์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ ๋™์ ์ธ ๋ฐ์ดํ„ฐ(state)๋ฅผ ๊ด€๋ฆฌํ•ด์ฃผ๋Š” hook์ด๋‹ค.

import React, { useState } from 'react';
function Example() {
  // "count"๋ผ๋Š” ์ƒˆ ์ƒํƒœ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

useState๋Š” ๋ฐฐ์—ด ๋น„๊ตฌ์กฐ๋ถ„ํ•ด ํ• ๋‹น์„ ํ†ตํ•ด ํ˜„์žฌ state๊ฐ’๊ณผ state๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค.
useState ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋„ฃ๋Š” ๊ฐ’์€ state์˜ ์ดˆ๊ธฐ ๊ฐ’์— ํ•ด๋‹น๋˜๊ณ , ๊ฐ’์„ ๋ฐ”๋€Œ๊ธฐ ์œ„ํ•ด setterํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์—์„œ ์‚ฌ์šฉํ•˜๋˜ state์™€ ๋‹ฌ๋ฆฌ ์ดˆ๊ธฐ ๊ฐ’์€ ๊ฐ์ฒด๊ฐ€ ์•„๋‹Œ primitive type ๊ฐ’์„ ๋„ฃ์–ด์ค„ ์ˆ˜ ์žˆ๊ณ  ์ปดํฌ๋„ŒํŠธ ๋‚ด์— ์—ฌ๋Ÿฌ๊ฐœ๋ฅผ ์‚ฌ์šฉ ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

useEffect

useEffect๋Š” react class ๋ฌธ๋ฒ•์—์„œ componentDidMount, componentDidUpdate, componentWillUnmount๊ฐ€ ํ•ฉ์ณ์ง„ ๊ธฐ๋Šฅ์ด๋‹ค.
๊ณต์‹ ๋ฌธ์„œ์—์„œ๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋žœ๋”๋ง ๋œ ์ดํ›„์— ์–ด๋–ค ์ผ์„ ์ˆ˜ํ–‰ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” hook์ด๋ผ๊ณ  ํ•œ๋‹ค.
react๋Š” effect๊ฐ€ ์ˆ˜ํ–‰๋˜๋Š” ์‹œ์ ์— ์ด๋ฏธ DOM์ด ์—…๋ฐ์ดํŠธ๋˜์—ˆ์Œ์„ ๋ณด์žฅํ•ด์ค€๋‹ค.

function Example() {
  const [count, setCount] = useState(0);

  // componentDidMount, componentDidUpdate์™€ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค
  useEffect(() => {
    // ๋ธŒ๋ผ์šฐ์ € API๋ฅผ ์ด์šฉํ•ด ๋ฌธ์„œ์˜ ํƒ€์ดํ‹€์„ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค
    document.title = `You clicked ${count} times`;
  });
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

useEffect ์‚ฌ์šฉ๋ฒ•

  • ์ฒซ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์—๋Š” ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋œ๋‹ค.
  • ๋‘๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” dependency ๋ฐฐ์—ด์ด ์˜ต์…”๋„๋กœ ์ฃผ์–ด์ง€๋Š”๋ฐ deps ๋ฐฐ์—ด ์•ˆ ๋ฐ์ดํ„ฐ๊ฐ€ update๊ฐ€ ๋˜๋ฉด useEffect์˜ ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋œ๋‹ค.
    : ์˜ต์…”๋„์ด๊ธฐ ๋•Œ๋ฌธ์— deps ๋ฐฐ์—ด์„ ๋„ฃ์ง€ ์•Š์œผ๋ฉด ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋žœ๋”๋ง ๋  ๋•Œ ๋งˆ๋‹ค ํ˜ธ์ถœ๋˜๊ณ ,
    ๋นˆ ๋ฐฐ์—ด์ผ ๊ฒฝ์šฐ ์ปดํฌ๋„ŒํŠธ๊ฐ€ mount ๋์„ ๋•Œ๋งŒ ์‹คํ–‰๋œ๋‹ค.
  • ๋งˆ์ง€๋ง‰์œผ๋กœ cleanup ํ•จ์ˆ˜๋Š” useEffect์—์„œ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ˜•์‹์œผ๋กœ ์‚ฌ์šฉ๋œ๋‹ค.
    • cleanup ํ•จ์ˆ˜๋Š” deps๊ฐ€ ๋นˆ ๋ฐฐ์—ด์ผ ๊ฒฝ์šฐ unmount๋  ๋•Œ ์‹คํ–‰๋œ๋‹ค.
    • deps ๋ฐฐ์—ด์— ํŠน์ • ๊ฐ’์„ ๋„ฃ๊ฒŒ ๋œ๋‹ค๋ฉด ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ฒ˜์Œ mount ๋  ๋•Œ๋„ ์‹คํ–‰๋˜๊ณ , deps์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฐ”๋€Œ๊ธฐ ์ง์ „์—๋„ ํ˜ธ์ถœ์ด ๋˜๊ณ  unmount๋  ๋•Œ๋„ ํ˜ธ์ถœ๋œ๋‹ค.
  • useEffect ์•ˆ์—์„œ ์‚ฌ์šฉ๋˜๋Š” state๋‚˜ props๊ฐ€ ์žˆ๋‹ค๋ฉด deps ์•ˆ์— ๋„ฃ์–ด์ฃผ๋Š” ๊ฒƒ์ด ๊ทœ์น™์ด๋‹ค
  • ๊ทธ๋ ‡๊ฒŒ ํ•˜์ง€ ์•Š์œผ๋ฉด state๋‚˜ props๋ฅผ ์ง€์ •ํ•ด์ฃผ์ง€ ์•Š๊ฒŒ ๋œ๋‹ค.

๐Ÿ“Œ react๋Š” ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋žœ๋”๋ง๋˜๋ฉด ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋„ ๊ฐ™์ด ๋ฆฌ๋žœ๋”๋ง์„ ์‹คํ–‰ํ•˜์ง€๋งŒ ์‹ค์ œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฐ”๋€ ๋ถ€๋ถ„๋งŒ DOM์— ์ ์šฉ๋œ๋‹ค.
ํ•˜์ง€๋งŒ virtual DOM์—๋Š” ๋ชจ๋“  ๋ฆฌ๋žœ๋”๋ง์— ๋Œ€์‘ํ•˜๊ณ  ์žˆ๊ฒŒ ๋œ๋‹ค.

๐Ÿ“Œ react์˜ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ „์ฒด ๋‹ค์‹œ ์‹คํ–‰์‹œํ‚จ๋‹ค.
react hook์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด hook์— ์‚ฌ์šฉ๋œ ๋ฐ์ดํ„ฐ๋ฅผ react์—์„œ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅํ•ด๋‘ฌ์„œ ๋‹ค์‹œ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰์‹œ์ผœ๋„ ์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ๊ฐ€ ์•„๋‹Œ ๋ณ€๊ฒฝ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์œ ์ง€์‹œ์ผœ์ฃผ๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

useRef

๋จผ์ € ref๋Š” render์—์„œ ์ƒ์„ฑ๋œ DOM ๋…ธ๋“œ๋‚˜ ๋ฆฌ์•กํŠธ ์—˜๋ฆฌ๋จผํŠธ์— ์ ‘๊ทผํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

๊ณต์‹๋ฌธ์„œ ref๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•  ๋•Œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • ํฌ์ปค์Šค, ํ…์ŠคํŠธ ์„ ํƒ์˜์—ญ, ํ˜น์€ ๋ฏธ๋””์–ด์˜ ์žฌ์ƒ์„ ๊ด€๋ฆฌํ•  ๋•Œ.
  • ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ง์ ‘์ ์œผ๋กœ ์‹คํ–‰์‹œํ‚ฌ ๋•Œ.
  • ์„œ๋“œ ํŒŒํ‹ฐ DOM ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ React์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•  ๋•Œ.

useRef๋Š” .current ํ”„๋กœํผํ‹ฐ๋กœ ์ „๋‹ฌ๋œ ์ธ์ž๋กœ ์ดˆ๊ธฐํ™” ๋œ ๊ฐ์ฒด๋ฅผ ๊ฐ€์ง„๋‹ค.
์ฆ‰ .current ํ”„๋กœํผํ‹ฐ์— ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ๊ฐ’์„ ๋‹ด๊ณ  ์žˆ๋Š” ์ƒ์ž๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด๋‹ค.
useRef๋Š” ์ˆœ์ˆ˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— useRef ๋‚ด์šฉ์ด ๋ณ€๊ฒฝ๋˜๋ฉด ๊ทธ๊ฒƒ์„ ์•Œ๋ ค์ฃผ์ง€ ์•Š๋Š”๋‹ค.
๋ฆฌ์•กํŠธ์—์„œ DOM ๋…ธ๋“œ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์ฝœ๋ฐฑ ref๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    // `current` points to the mounted text input element
    inputEl.current.focus();
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

useMemo

useMemo๋Š” ์„ฑ๋Šฅ ์ตœ์ ํ™”์— ์‚ฌ์šฉ๋˜๋Š” hook์ด๋‹ค.
๋ฉ”๋ชจ์ด์ œ์ด์…˜์„ ํ•ด์ค€๋‹ค๋Š” ๋œป์œผ๋กœ useMemo๋กœ ์‚ฌ์šฉ๋˜๋Š”๋ฐ, ํŠน์ • ๊ฒฐ๊ณผ ๊ฐ’์„ ์žฌ์‚ฌ์šฉ ํ•ด์ค€๋‹ค.

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

useMemo์˜ ์‚ฌ์šฉ๋ฒ•

  • ์ƒ์„ฑํ•จ์ˆ˜์™€ ์˜์กด์„ฑ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐฐ์—ด์— ์ „๋‹ฌํ•ด์ค€๋‹ค.
    • ๋ฐฐ์—ด์— ๋‹ด๊ธด ์˜์กด์„ฑ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งŒ ๋žœ๋”๋ง์„ ํ•ด์ฃผ๊ณ , ๋ฐฐ์—ด์ด ์—†๋Š” ๊ฒฝ์šฐ ๋งค ๋žœ๋”๋ง์— ์ƒˆ ๊ฐ’์„ ๊ณ„์‚ฐํ•ด์ค€๋‹ค.

useCallback

ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ณ„์† ํ˜ธ์ถœ๋˜์–ด๋„ ๋™์ผํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ์˜ ์ง€์—ญํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์‹ถ์„๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.
useCallback๋Š” ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ์˜ state๋‚˜ props๊ฐ€ ๋ณ€๊ฒฝ๋˜์–ด๋„ ์บ์‹œ์— ์ €์žฅ๋œ ์บก์ณ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰์‹œํ‚จ๋‹ค.

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);

useCallbak์˜ ์‚ฌ์šฉ๋ฒ•

  • ๋‘๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ deps ๋ฐฐ์—ด์— ๋ณ€๊ฒฝํ•ด์ค˜์•ผํ•˜๋Š” state๋‚˜ props๋ฅผ ๋„ฃ์–ด์ค˜์•ผํ•œ๋‹ค.
  • ๋˜ํ•œ ํ•จ์ˆ˜์•ˆ์—์„œ ์‚ฌ์šฉํ•˜๋Š” state๋‚˜ props๊ฐ€ ์žˆ๋‹ค๋ฉด deps ๋ฐฐ์—ด์— ๋„ฃ์–ด์ค˜์•ผํ•œ๋‹ค.

useReducer

useReducer๋Š” ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•  ๋•Œ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•œ hook ํ•จ์ˆ˜์ด๊ณ , ์™ธ๋ถ€ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ž‘์„ฑํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด useState์™€ ๋‹ค๋ฅธ์ ์ด๋‹ค.

const initialState = {count: 0};

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}

useReducer์˜ ์‚ฌ์šฉ๋ฒ•

  • reducer ํ•จ์ˆ˜
    • state์™€ action์„ ์ธ์ž๋กœ ๋ฐ›๋Š”๋‹ค.
      • state: ํ˜„์žฌ ์ƒํƒœ
      • action: ์—…๋ฐ์ดํŠธ๋ฅผ ์œ„ํ•œ ์ •๋ณด
    • dispatch ํ•จ์ˆ˜
      • action์„ ์‹คํ–‰์‹œํ‚ค๋Š” ํ•จ์ˆ˜์ด๊ณ , dispatch์•ˆ์— action์„ ๋„ฃ์œผ๋ฉด reducerํ•จ์ˆ˜์—์„œ action์— ํ•ด๋‹นํ•˜๋Š” ์ •๋ณด๋กœ state๊ฐ’์„ ์—…๋ฐ์ดํŠธ ์‹œํ‚จ๋‹ค.
    • useReducer ํ•จ์ˆ˜
      • ์ฒซ๋ฒˆ์งธ ์ธ์ž์—๋Š” reducer ํ•จ์ˆ˜๋ฅผ ๋„ฃ๊ณ , ๋‘๋ฒˆ์งธ ์ธ์ž์—๋Š” ์ดˆ๊ธฐ state๊ฐ’์„ ๋„ฃ๋Š”๋‹ค.
      • ๊ฒฐ๊ณผ๊ฐ’์œผ๋กœ state์™€ dispatch ํ•จ์ˆ˜๋ฅผ ๋ฐ›์•„์˜จ๋‹ค.
        • state๋Š” ์ดˆ๊ธฐ์—๋Š” ๋‘๋ฒˆ์งธ ์ธ์ž์—์„œ ์ง€์ •ํ•œ ์ดˆ๊ธฐ state๊ฐ’์œผ๋กœ ์„ธํŒ…๋˜๊ณ , dispatch ํ•จ์ˆ˜ ์‹คํ–‰์œผ๋กœ reducer๋ฅผ ์‹คํ–‰์‹œ์ผœ ์—…๋ฐ์ดํŠธ ๋œ ๊ฐ’์„ ๋ฐ›์•„์˜จ๋‹ค.

๐Ÿ“Œ state ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ ์ƒˆ๋กœ์šด state ๊ฐ’์œผ๋กœ ๋Œ€์ฒด(replace)๋˜๋Š” ๊ฒƒ์ด์ง€ ๊ธฐ์กด state ๊ฐ’์„ ๋ณ€๊ฒฝ(modify)ํ•˜๊ฑฐ๋‚˜ ๋ฎ์–ด์“ฐ์ง€(overwrite) ์•Š๋Š”๋‹ค. (๋ฐ์ดํ„ฐ ๋ถˆ๋ณ€์„ฑ ์œ ์ง€)

profile
์ •๋ฆฌํ•˜๊ณ  ๊ธฐ์–ตํ•˜๋Š” ๊ณณ

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