React 에는 다양한 Hook들이 존재하는데 이번 글에서는 자주 사용되는 useState, useEffect, useRef, useContext에 대해 언급해보고자 한다.
useState는 컴포넌트 내에서 상태를 선언하고 관리하기 위해 사용된다. 상태 값과 그 상태를 변경하는 함수를 반환하며, 초기값을 인자로 전달할 수 있다. 상태는 컴포넌트가 다시 렌더링될 때도 유지되며, 상태가 변경되면 해당 컴포넌트는 다시 렌더링된다.
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0); // 초기값을 0으로 설정
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
위 예시에서는 count라는 상태를 선언하고, 버튼을 클릭할 때마다 setCount로 상태를 변경한다. 그리고 상태의 변경에 따라 컴포넌트가 자동으로 다시 렌더링 될 것이다.
useEffect는 컴포넌트가 렌더링될 때 특정 작업을 수행하도록 한다. 마운트(처음 렌더링), 업데이트(상태나 props 변경), 언마운트(컴포넌트가 사라질 때)시에 특정 동작을 실행할 수 있다. 그리고 의존성 배열을 통해 특정 값이 변경될 때만 실행되도록 제어할 수 있다.
import React, { useState, useEffect } from 'react';
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => { // 컴포넌트 마운트 시 실행
setSeconds(prev => prev + 1);
}, 1000);
return () => clearInterval(interval); // 컴포넌트 언마운트 시 정리(cleanup)
}, []); // 빈 배열을 넣으면 마운트 시에만 실행됨
return <div>Seconds: {seconds}</div>;
}
위 예시에서는 useEffect에서 클린업 함수(return ())를 통해 컴포넌트가 언마운트될 때 타이머를 해제한다. 의존성 배열은 빈 배열([])로 설정되어 있기에 해당 useEffect는 컴포넌트가 처음 마운트 될 때만 실행된다.
(컴포넌트는 보통 조건부 렌더링이나 페이지 전환 때 언마운트 된다.)
useRef는 주로 DOM 요소나 값의 참조를 유지하기 위해 사용되며, 컴포넌트가 다시 렌더링되더라도 변경되지 않는 값을 저장할 때 유용하다. 저장된 값에는 current 프로퍼티를 통해 접근할 수 있다.
import React, { useRef } from 'react';
function FocusInput() {
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus(); // input 요소에 포커스
};
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={focusInput}>Focus Input</button>
</div>
);
}
해당 코드에서는 useRef를 통해 input요소에 접근하고, 버튼 클릭 시 해당 요소에 포커스를 설정한다. 또한 useRef는 값이 변경되어도 컴포넌트가 리렌더링되지 않기에, 단순히 요소의 참조나 특정 값을 저장할 때 유용하다.
useContext는 Context API와 함께 주로 전역 상태를 관리할 때 사용되며, 부모 컴포넌트에서 자식 컴포넌트로 직접 props를 전달하지 않고도 상태를 사용할 수 있다.
Context API에는 세 가지 필수 개념이 있다.
createContext : context를 생성useContext : context를 구독하고 해당 context의 현재 값을 읽음Provider : context를 하위 컴포넌트에게 전달import React, { createContext, useContext } from 'react';
// Context 생성
export const FamilyContext = createContext();
createContext를 사용하여 FamilyContext를 생성했다. 이 Context는 사용해 전역 상태를 관리할 수 있다.
import React, { useContext } from 'react';
import { FamilyContext } from '../context/FamilyContext';
function FamilyMember() {
const family = useContext(FamilyContext); // FamilyContext에서 값 가져오기
return <div>Family Member: {family.name}</div>;
}
위 코드에서는 useContext를 사용해 FamilyContext로부터 값을 받아와서 컴포넌트에서 쉽게 사용할 수 있다. 이로 인해 복잡한 props전달 없이 필요한 데이터를 여러 컴포넌트에서 공유할 수 있다.

import React from 'react';
import { FamilyContext } from '../context/FamilyContext';
import FamilyMember from './FamilyMember';
function FamilyProvider() {
const familyData = { name: 'John', age: 45 };
return (
<FamilyContext.Provider value={familyData}>
<FamilyMember />
</FamilyContext.Provider>
);
}
FamilyContext.Provider는 value prop을 통해 familyData를 전달한다. 이제 FamilyMember 컴포넌트는 useContext(FamilyContext)를 사용하여 이 데이터에 접근하고 사용할 수 있다.