React Hooks 설명: 2026년을 위한 시각 가이드
Source: Dev.to
해당 링크에 포함된 텍스트를 제공해 주시면, 요청하신 대로 한국어로 번역해 드리겠습니다. 현재는 본문 내용이 없으므로 번역을 진행할 수 없습니다. 텍스트를 복사해서 알려주시면 바로 번역해 드리겠습니다.
useState
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
setCount(count + 1)}>
Clicked {count} times
);
}
When to use: 렌더링 사이에 컴포넌트가 기억해야 하는 모든 것 — 폼 값, 토글, 카운터 등.
Gotcha: 상태 업데이트는 비동기적으로 이루어집니다.
// ❌ This won't work as expected
setCount(count + 1);
setCount(count + 1); // Both use the same `count` value
// ✅ Use the updater function instead
setCount(prev => prev + 1);
setCount(prev => prev + 1); // Now it's +2
Source:
useEffect
import { useEffect, useState } from 'react';
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
// Runs after every render where userId changes
fetch(`/api/users/${userId}`)
.then(r => r.json())
.then(setUser);
}, [userId]); // dependency array
return {user?.name};
}
의존성 배열
| 의존성 | 동작 |
|---|---|
[] | 마운트 시 한 번 실행 |
[value] | value가 변경될 때 실행 |
| none | 매 렌더링 후마다 실행 (보통 잘못된 사용) |
정리
useEffect(() => {
const subscription = subscribe(userId);
return () => {
subscription.unsubscribe(); // cleanup!
};
}, [userId]);
useContext
import { createContext, useContext, useState } from 'react';
// 1. Create the context
const ThemeContext = createContext('light');
// 2. Provide it at the top
function App() {
const [theme, setTheme] = useState('dark');
return (
);
}
// 3. Use it anywhere in the tree
function Button() {
const { theme } = useContext(ThemeContext);
return Click me;
}
useRef
import { useRef } from 'react';
function TextInput() {
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus();
};
return (
<>
Focus
);
}
리렌더를 트리거하지 않아야 하는 값을 저장하는 데에도 유용합니다:
const renderCount = useRef(0);
renderCount.current += 1; // Doesn't cause re-render
useMemo
function ProductList({ products, minPrice }) {
// Recalculates only when `products` or `minPrice` change
const filtered = useMemo(() => {
return products.filter(p => p.price >= minPrice);
}, [products, minPrice]);
return (
{filtered.map(p => - {p.name}
)}
);
}
When to use: 실제로 비용이 많이 드는 계산이며, 성능 문제가 발생한다고 측정된 경우에만 사용합니다.
useCallback
import { useCallback } from 'react';
function Parent({ id }) {
// Without useCallback, a new function is created every render
const handleClick = useCallback(() => {
doSomethingWith(id);
}, [id]);
return ;
}
사용 시기: React.memo 로 감싼 자식 컴포넌트에 콜백을 전달할 때 불필요한 재렌더링을 방지하기 위해.
useReducer
import { useReducer } from 'react';
const initialState = { count: 0, error: null, loading: false };
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { ...state, count: state.count + 1 };
case 'decrement':
return { ...state, count: state.count - 1 };
case 'reset':
return initialState;
default:
return state;
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
Count: {state.count}
dispatch({ type: 'increment' })}>+
dispatch({ type: 'decrement' })}>-
);
}
useState 대신 사용할 때: 여러 개의 상태가 서로 관련되어 함께 변경될 때.
커스텀 훅 (조합성)
// Custom hook for API calls
function useApi(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
setLoading(true);
fetch(url)
.then(r => {
if (!r.ok) throw new Error(`HTTP ${r.status}`);
return r.json();
})
.then(data => { setData(data); setLoading(false); })
.catch(err => { setError(err.message); setLoading(false); });
}, [url]);
return { data, loading, error };
}
// Using the custom hook
function UserList() {
const { data, loading, error } = useApi('/api/users');
if (loading) return ;
if (error) return ;
return
{data.map(u => - {u.name}
)}
;
}
Hook 개요
| Hook | 목적 |
|---|---|
useState | 로컬 상태 |
useEffect | 부수 효과, 데이터 가져오기 |
useContext | props 없이 상태 공유 |
useRef | DOM 레퍼런스, 가변 값 |
useMemo | 비싼 계산 메모이제이션 |
useCallback | 안정적인 콜백 참조 |
useReducer | 복잡한 상태 로직 |