개요
저번에 React Lifecycle에 대해 공부하면서, 함수형 컴포넌트에서는 생명주기와 state를 적용하기 위해서는 Hook이라는 것을 사용해야 한다고 했는데 오늘은 React Hook에 대한 내용을 정리해보겠다.
1. React Hook 이란?
함수형 컴포넌트에서도 상태(state)와 생명주기 메서드를 사용할 수 있도록 해주는 기능이다.
이전에는 클래스 컴포넌트를 사용해야만 state나 componentDidMount 같은 생명주기 메서드를 활용할 수 있었지만, Hook을 통해 함수형 컴포넌트에서도 동일한 기능을 구현할 수 있다.
하나씩 어떤 종류가 있는지 알아보자.
2. React Hook 종류
2-1. useState
-> 사용자의 입력 값을 저장하거나 UI에서 값이 변경될 때마다 다시 렌더링 해야하는 등 상태를 선언하고 관리할 때 사용하는 Hook이다.
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>현재 카운트: {count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
);
}
-> useState(초기값)을 호출하면 [상태값, 상태변경함수] 배열이 반환된다.
-> count는 현재 상태 값이고, setCount를 호출하면 새로운 상태 값으로 업데이트 된다.
-> 사용자가 버튼을 클릭할 때마다 setCount(count+1)을 실행해 count 값을 증가시키고, 컴포넌트가 다시 렌더링된다.
2-2 useEffect
-> 컴포넌트가 렌더링 될 때 특정 로직을 실행하도록 도와주는 Hook이다.
-> API 호출할 때, 컴포넌트가 처음 마운트되거나 업데이트될 때 실행할 코드가 있을 때
-> 이벤트 리스너를 등록하거나 정리할 때 사용한다.
import { useState, useEffect } from "react";
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSeconds((prev) => prev + 1);
}, 1000);
return () => clearInterval(interval);
}, []);
return <p>타이머: {seconds}초</p>;
}
-> useEffect는 기본적으로 컴포넌트가 렌더링될 때마다 실행된다.
-> 두 번째 인자로 빈 배열 []을 전달하면, 처음 마운트될 때만 실행된다.
-> return 함수는 클린업 함수로, 컴포넌트가 언마운트될 때 실행된다.
-> useEffect의 의존성 배열에 특정 변수를 넣으면 해당 값이 변경될 때마다 useEffect가 다시 실행된다.
2-3. useReducer
-> useState와 유사하지만, 더 복잡한 상태 로직을 관리할 때 유용한 Hook이다.
-> 상태와 함께 동작할 reducer 함수를 사용해 상태를 업데이트한다.
import { useReducer } from "react";
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 };
case "reset":
return initialState;
default:
return state;
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<p>카운트: {state.count}</p>
<button onClick={() => dispatch({ type: "increment" })}>+1</button>
<button onClick={() => dispatch({ type: "decrement" })}>-1</button>
<button onClick={() => dispatch({ type: "reset" })}>리셋</button>
</div>
);
}
-> useReducer(reducer, initialState)를 호출하면 [state, dispatch] 배열이 반환된다.
-> reducer 함수는 현재 상태(state)와 액션(action)을 받아 새로운 상태를 반환한다.
-> dispatch 함수를 호출하면 action을 reducer 함수에 전달해 상태를 변경할 수 있다.
2-4. useRef
-> React에서 직접 DOM 요소에 접근하거나, 컴포넌트의 상태를 렌더링 없이 유지할 때 사용하는 Hook이다.
-> DOM 요소에 직접 접근해야 할 때
-> 렌더링 없이 값을 저장하고 싶을 때 사용한다.
import { useRef, useEffect } from "react";
function FocusInput() {
const inputRef = useRef(null);
useEffect(() => {
inputRef.current.focus(); // 마운트 시 input 요소에 포커스
}, []);
return <input ref={inputRef} placeholder="자동 포커스" />;
}
-> useRef(null)을 호출하면 ref 객체가 생성된다.
-> inputRef.current에 input 요소가 저장되어 직접 접근할 수 있다.
-> useEffect 내에서 inputRef.current.focus()를 호출해 자동으로 포커스를 준다.
import { useRef, useState, useEffect } from "react";
function Timer() {
const [count, setCount] = useState(0);
const countRef = useRef(0);
useEffect(() => {
const interval = setInterval(() => {
countRef.current += 1;
console.log(`렌더링 없이 증가: ${countRef.current}`);
}, 1000);
return () => clearInterval(interval);
}, []);
return (
<div>
<p>렌더링된 값: {count}</p>
<button onClick={() => setCount(count + 1)}>렌더링 업데이트</button>
</div>
);
}
-> countRef는 컴포넌트가 다시 렌더링 될 때 값이 유지된다.
-> countRef.current를 직접 변경해도 컴포넌트가 다시 렌더링되지 않는다.
-> setCount를 통해 상태를 변경해야만 실제 렌더링이 일어난다.
3. React Hook 사용 규칙
1) Hook은 최상위 레벨에서만 호출해야 한다.
-> Hook을 if, for, while 문 내부에서 호출하면 안된다.
-> 항상 함수 컴포넌트의 최상위에서 호출해야 한다.
// 잘못된 예제
function Example() {
if (someCondition) {
const [count, setCount] = useState(0); // ❌ 조건문 안에서 Hook 사용 금지
}
}
// 올바른 예제
function Example() {
const [count, setCount] = useState(0); // ✅ 최상위에서 호출
return <p>{count}</p>;
}
2) Hook은 함수 컴포넌트 또는 커스텀 Hook에서만 사용해야 한다.
-> 일반 JavaScript 함수 및 클래스 컴포넌트에서는 사용할 수 없다.
3) Hook의 호출 순서는 항상 일정해야 한다.
-> Hook의 호출 순서가 매 렌더링마다 달라지면 안된다.
-> 조건문 안에서 useState, useEffect 등의 Hook을 호출한다면 React가 Hook을 추적하는 순서를 예측할 수 없어 문제가 발생할 수 있다.
'Web > React' 카테고리의 다른 글
[React] reactstrap이란? (0) | 2025.02.17 |
---|---|
[React] 조건부 렌더링(Conditional Rendering) (0) | 2025.02.15 |
[React] React LifeCycle (0) | 2025.02.11 |
[React] State란? (0) | 2025.02.11 |
[React] Component와 Props (1) | 2025.02.11 |