리액트 훅(React Hooks)은
함수형 컴포넌트에서 상태(state)와 라이프사이클(lifecycle) 기능을 사용할 수 있게 해주는 기능입니다.
리액트 16.8 버전에서 도입되었으며, 클래스형 컴포넌트의 복잡성을 피하고,
함수형 컴포넌트의 장점을 살릴 수 있도록 돕습니다. 주요 훅은 다음과 같습니다:
1. useState
useState 훅은 컴포넌트에서 상태 변수를 선언할 수 있게 합니다.
import React, { useState } from 'react';
function Example() {
const [count, setCount] = useState(0); // 초기 값 0
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
- useState는 상태 변수와 이를 업데이트할 함수를 반환합니다.
- 상태 변수의 초기값을 인자로 전달합니다.
2. useEffect
useEffect 훅은 컴포넌트가 렌더링된 이후에 수행될 작업을 설정할 수 있게 합니다.
import React, { useEffect, useState } from 'react';
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]); // count가 변경될 때마다 실행
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
- useEffect는 사이드 이펙트를 수행하는 데 사용됩니다.
- 두 번째 인자로 의존성 배열을 받아, 해당 배열에 있는 값이 변경될 때만 이펙트가 실행됩니다.
- 빈 배열 []을 전달하면 컴포넌트가 처음 마운트될 때만 실행됩니다.
- 반환값으로 클린업 함수를 제공하여 컴포넌트 언마운트 시 실행할 작업을 정의할 수 있습니다.
3. useContext
useContext 훅은 컨텍스트를 사용하여 컴포넌트 트리 전체에 걸쳐 값을 전달할 수 있게 합니다.
import React, { useContext } from 'react';
const ThemeContext = React.createContext('light');
function ThemedButton() {
const theme = useContext(ThemeContext);
return <button style={{ background: theme === 'dark' ? '#333' : '#fff' }}>I am styled by theme context!</button>;
}
function App() {
return (
<ThemeContext.Provider value="dark">
<ThemedButton />
</ThemeContext.Provider>
);
}
- useContext는 컨텍스트 객체를 인자로 받아 현재 컨텍스트 값을 반환합니다.
4. useReducer
useReducer 훅은 복잡한 상태 로직을 처리하거나, 상태가 여러 종류일 때 사용합니다. Redux의 reducer와 유사한 형태로 작동합니다.
import React, { 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 };
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
</div>
);
}
- useReducer는 상태와 디스패치 함수를 반환합니다.
- 복잡한 상태 관리를 단순화할 수 있습니다.
5. 커스텀 훅(Custom Hooks)
커스텀 훅은 여러 훅을 조합해 재사용 가능한 로직을 만들 수 있는 기능입니다.
import React, { 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 DataComponent() {
const data = useFetch('https://api.example.com/data');
if (!data) return <div>Loading...</div>;
return <div>{data.title}</div>;
}
- 커스텀 훅은 use로 시작하는 이름을 가지며, 내부에서 다른 훅을 호출할 수 있습니다.
- 복잡한 로직을 컴포넌트 외부로 추출해 코드 재사용성을 높일 수 있습니다.
이 외에도 useMemo, useCallback, useRef 등 다양한 훅이 있습니다.
useMemo, useCallback, useRef는 성능 최적화와 특정한 DOM 요소에 접근하는 등의 특수한 작업에 유용합니다.
각 훅의 사용법과 예제를 살펴보겠습니다.
1. useMemo
useMemo 훅은 값의 계산을 메모이제이션(Memoization)하여 성능을 최적화하는 데 사용됩니다. 특정 값이 변경될 때만 계산을 수행하여 불필요한 계산을 피할 수 있습니다.
import React, { useMemo, useState } from 'react';
function ExpensiveComponent({ num }) {
const [count, setCount] = useState(0);
const expensiveCalculation = (num) => {
console.log('Calculating...');
return num * 2;
};
const memoizedValue = useMemo(() => expensiveCalculation(num), [num]);
return (
<div>
<p>Memoized Value: {memoizedValue}</p>
<button onClick={() => setCount(count + 1)}>Re-render</button>
<p>Count: {count}</p>
</div>
);
}
- useMemo는 첫 번째 인자로 함수, 두 번째 인자로 의존성 배열을 받습니다.
- 의존성 배열의 값이 변경될 때만 함수가 실행되고, 그렇지 않으면 이전 계산 값을 반환합니다.
- 이는 특히 계산 비용이 높은 함수의 결과를 메모이제이션할 때 유용합니다.
2. useCallback
useCallback 훅은 함수를 메모이제이션하여 성능을 최적화하는 데 사용됩니다. 컴포넌트가 렌더링될 때마다 동일한 함수 인스턴스를 재사용할 수 있게 합니다.
import React, { useState, useCallback } from 'react';
function Button({ onClick }) {
return <button onClick={onClick}>Click me</button>;
}
function ParentComponent() {
const [count, setCount] = useState(0);
const [text, setText] = useState('');
const handleClick = useCallback(() => {
setCount(count + 1);
}, [count]);
return (
<div>
<Button onClick={handleClick} />
<input value={text} onChange={(e) => setText(e.target.value)} />
<p>Count: {count}</p>
</div>
);
}
- useCallback은 첫 번째 인자로 함수를, 두 번째 인자로 의존성 배열을 받습니다.
- 의존성 배열의 값이 변경될 때만 새로운 함수 인스턴스를 생성하고, 그렇지 않으면 이전 함수를 반환합니다.
- 이는 자식 컴포넌트에 콜백 함수를 전달할 때 유용하며, 불필요한 리렌더링을 방지할 수 있습니다.
3. useRef
useRef 훅은 DOM 요소나 클래스 컴포넌트 인스턴스에 접근하거나, 값이 변경되어도 리렌더링되지 않는 변수를 관리할 때 사용됩니다.
import React, { useRef, useEffect } from 'react';
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
inputEl.current.focus();
};
return (
<div>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</div>
);
}
- useRef는 초기 값을 인자로 받아, current 속성을 가진 객체를 반환합니다.
- 반환된 객체는 컴포넌트의 전체 수명 동안 유지되며, DOM 요소에 접근할 때 유용합니다.
- useRef로 관리하는 값은 변경되어도 컴포넌트를 리렌더링하지 않습니다.
4. useMemo, useCallback, useRef 비교
- useMemo: 계산 비용이 높은 값을 메모이제이션하여 성능 최적화.
- useCallback: 함수 인스턴스를 메모이제이션하여 자식 컴포넌트의 불필요한 리렌더링 방지.
- useRef: DOM 요소에 접근하거나 컴포넌트가 리렌더링되어도 유지되는 값을 관리.
각 훅은 특정한 상황에서 성능 최적화와 코드의 효율성을 높이는 데 유용하며,
적절한 사용법을 이해하고 적용하는 것이 중요합니다.
각 훅은 각각 특정한 상황에서 유용하게 사용할 수 있습니다.
리액트 훅은 함수형 컴포넌트의 기능을 강화하고,
클래스형 컴포넌트의 복잡성을 줄이는 데 큰 기여를 하고 있습니다.