본문 바로가기
개발일지/React

[21] React hook 종류

by 꾸주니=^= 2024. 12. 21.

훅(Hook)은 함수형 컴포넌트에서 상태 관리와 생명주기 로직을 손쉽게 구현하도록 돕는 React의 핵심 기능입니다. 주요 훅과 그 사용법을 아래에 정리해 보겠습니다.

 

1. 기본 훅 (가장 많이 사용하는 훅)

1.1 useState

  • 역할: 컴포넌트 상태를 선언하고 관리.
  • 사용법:
import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0); // 초기 상태를 0으로 설정

  return (
    <div>
      <p>현재 카운트: {count}</p>
      <button onClick={() => setCount(count + 1)}>증가</button>
    </div>
  );
}
  • 설명:
    • useState는 배열을 반환합니다.
    • 첫 번째 요소: 현재 상태 값 (count).
    • 두 번째 요소: 상태를 업데이트하는 함수 (setCount).

 

1.2 useEffect

  • 역할: 사이드 이펙트(데이터 가져오기, DOM 업데이트 등)를 처리.
  • 사용법:
import React, { useState, useEffect } from 'react';

function Timer() {
  const [time, setTime] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setTime((prevTime) => prevTime + 1);
    }, 1000);

    return () => clearInterval(interval); // 컴포넌트가 제거될 때 정리
  }, []); // 빈 배열: 컴포넌트가 처음 렌더링될 때만 실행

  return <p>시간: {time}초</p>;
}
  • 설명:
    • 첫 번째 인자: 실행할 함수.
    • 두 번째 인자(의존성 배열): 해당 배열의 값이 변경될 때만 함수 실행.
    • 배열이 비어 있으면 컴포넌트가 처음 렌더링될 때만 실행.

 

1.3 useContext

  • 역할: 컴포넌트 트리의 깊숙한 곳에 데이터를 전달할 때 사용.
  • 사용법:
import React, { useContext, createContext } from 'react';

const ThemeContext = createContext('light'); // 기본값: 'light'

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Toolbar />
    </ThemeContext.Provider>
  );
}

function Toolbar() {
  return <ThemedButton />;
}

function ThemedButton() {
  const theme = useContext(ThemeContext); // 'dark' 사용
  return <button style={{ backgroundColor: theme === 'dark' ? 'black' : 'white' }}>테마 버튼</button>;
}

 

 

2. 추가 훅 (중요하지만 덜 사용)

2.1 useReducer

  • 역할: 복잡한 상태 로직을 처리 (Redux의 Reducer와 비슷).
  • 사용법:
import React, { useReducer } from 'react';

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, { count: 0 });

  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
    </div>
  );
}

 

2.2 useCallback

  • 역할: 함수를 메모이제이션하여 렌더링 성능 최적화.
  • 사용법:
import React, { useState, useCallback } from 'react';

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

  const increment = useCallback(() => {
    setCount((c) => c + 1);
  }, []); // 의존성 배열

  return <button onClick={increment}>증가: {count}</button>;
}

컴포넌트가 다시 렌더링되어도 동일한 함수 참조를 유지.

 

2.3 useMemo

  • 역할: 값을 메모이제이션하여 계산 비용을 최적화.
  • 사용법:
import React, { useState, useMemo } from 'react';

function ExpensiveCalculation({ num }) {
  const expensiveValue = useMemo(() => {
    console.log('Expensive calculation...');
    return num * 2;
  }, [num]);

  return <p>결과: {expensiveValue}</p>;
}

값이 변경되지 않으면 이전 값을 재사용.

 

2.4 useRef

  • 역할: DOM 요소나 값의 변경을 추적.
  • 사용법:
import React, { useRef, useEffect } from 'react';

function FocusInput() {
  const inputRef = useRef(null);

  useEffect(() => {
    inputRef.current.focus();
  }, []);

  return <input ref={inputRef} />;
}

 

2.5 useLayoutEffect

  • 역할: DOM 변경 후 동기적으로 실행 (useEffect와 비슷하나 실행 타이밍이 다름).
  • 사용법:
import React, { useLayoutEffect, useRef } from 'react';

function LayoutExample() {
  const divRef = useRef(null);

  useLayoutEffect(() => {
    console.log(divRef.current.getBoundingClientRect());
  }, []);

  return <div ref={divRef}>Hello</div>;
}

 

2.6 useImperativeHandle

  • 역할: 부모 컴포넌트가 자식의 DOM 노드 또는 함수에 접근하도록 허용.
  • 사용법:
import React, { useImperativeHandle, forwardRef, useRef } from 'react';

const FancyInput = forwardRef((props, ref) => {
  const inputRef = useRef();

  useImperativeHandle(ref, () => ({
    focus: () => inputRef.current.focus(),
  }));

  return <input ref={inputRef} />;
});

function App() {
  const inputRef = useRef();

  return (
    <div>
      <FancyInput ref={inputRef} />
      <button onClick={() => inputRef.current.focus()}>Focus</button>
    </div>
  );
}

 

3. Custom Hook

  • 역할: 훅을 조합하여 재사용 가능한 로직 생성.
  • 예제:
import { useState, useEffect } from 'react';

function useFetch(url) {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch(url)
      .then((response) => response.json())
      .then((data) => setData(data));
  }, [url]);

  return data;
}

function App() {
  const data = useFetch('https://jsonplaceholder.typicode.com/posts');

  return (
    <div>
      {data && data.map((post) => <p key={post.id}>{post.title}</p>)}
    </div>
  );
}

 

 


많이 사용하는 훅 요약

  1. useState: 상태 관리.
  2. useEffect: 사이드 이펙트 처리.
  3. useContext: 전역 상태 관리.
  4. useRef: DOM 접근 또는 값 저장.
  5. useMemo, useCallback: 성능 최적화.

 

각 Hook별 설명 및 요약

 

정리

React의 use로 시작하는 훅은 각기 다른 역할로 효율적인 상태 관리, 성능 최적화, DOM 접근 등을 돕습니다. 기본 훅인 useState, useEffect는 필수적으로 익히고, 필요에 따라 useReducer, useCallback 등을 활용하세요. Custom Hook은 반복되는 로직을 간소화하는 데 매우 유용합니다.