리액트 컴포넌트는 함수형 컴포넌트와 클래스형 컴포넌트로 나뉜다.
함수형 컴포넌트에 Hook이 나오기 전까지는, 일반적으로 클래스형 컴포넌트를 많이 사용했다.
하지만 클래스형 컴포넌트에서 상태(state)를 사용하고, 생명주기 메서드를 사용하는 방식은 많은 문제들과 불편함을 가지고 있었다.
React Hook은 클래스형 컴포넌트의 단점을 보완하여, 함수형 컴포넌트를 사용할 수 있도록 한다.
리액트 16.8 버전에 새로 도입된 기능으로, 함수형 컴포넌트에서 사용되는 몇 가지 기술들을 일컫는다.
리액트 훅은 함수형 컴포넌트가 클래스형 컴포넌트의 기능을 사용할 수 있도록 해주며 대표적인 예로는 useState, useEffect 등이 존재한다.
useState
useState는 상태를 관리하는 Hook으로 클래스형 컴포넌트에서만 사용 가능하던 State를 함수형 컴포넌트에서도 사용 가능 하도록 한 대표적인 기능이다.
선언방법
const [변수명, 상태를 업데이트 할 함수명] = useState(초기값)
useState로 선언된 변수는 상태(state)가 변할 때마다 페이지를 리렌더링 시키게 된다.
useState Example
import React, { useState } from 'react';
function Example() {
// "count"라는 새 상태 변수를 선언합니다
const [count, setCount] = useState(0);
// 버튼을 클릭할 때마다 기존의 state 기본값인 0에 1이 더해진다.
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
useEffect
useEffect는 화면이 렌더링 될 때마다, 특정 작업을 실행할 수 있도록 하는 Hook으로 일반적으로 sideEffect의 처리를 위해서 사용된다고 말한다.
sideEffect란?
컴포넌트가 화면에 렌더링 된 이후에 비동기로 처리되어야 하는 부수적인 효과들을 말한다.
선언방법
useEffect( () => {실행시킬 함수}, 의존성 배열)
의존성 배열에 따라 렌더링의 횟수를 조절할 수 있다.
useEffect Example
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
useMemo
컴포넌트의 성능을 최적화하는 데 사용한다
선언 방법
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
사용 시 주의할 점
useMemo은 어떻게 동작하는가
useMemo Example
import React, { useEffect, useState, useMemo } from 'react';
function UseMemoExample() {
const [localStates, setLocalStates] = useState({
number1: 0,
number2: 0
});
const fn_localStateChange = (e, stateName) => {
setLocalStates(prev => ({...prev,[stateName]: e.target.value}));
};
const doubleNumber = useMemo(() => {
console.log('Calculating doubleNumber');
const result = slowFunction(localStates.number1);
setLocalStates(prev => ({...prev, number2: result}));
return result;
}, [localStates.number1]);
function slowFunction(num) {
console.log('Calling slow function');
for (let i = 0; i <= 1000000000; i++) { }
return num * 2;
}
return (
<div>
<input
type="number"
value={localStates.number1}
onChange={e => fn_localStateChange(e, 'number1')}
/>
<div>Double: {doubleNumber}</div>
</div>
);
}
export default UseMemoExample;
useContext
컨텍스트는 컴포넌트 트리 전체에 전역적으로 데이터를 전달할 수 있다.
사용방법
1. Context 생성
const MyContext = React.createContext
createContext 함수를 호출하여 새로운 Context 객체를 만든다.
2. Provider로 값 제공
<MyContext.Provider value={/* 공유할 값 */}>
{/* 자식 컴포넌트 */}
</MyContext.Provider>
생성된 Context 객체는 Provider 컴포넌트를 갖고 있다. 이 컴포넌트는 하위 컴포넌트들에게 컨텍스트 값을 전달한다.
Provider의 value가 변경되면 해당 Context를 사용하는 모든 하위 컴포넌트가 리렌더링 된다
3. useContext로 값 사용
const value = React.useContext(MyContext);
useContext를 사용하여 함수 컴포넌트 내에서 컨텍스트 값을 구독할 수 있다.
특징
useContext Example
import React, { createContext, useContext, useState } from "react";
// AuthContext 생성
const AuthContext = createContext();
// AuthProvider로 값 제공
export const AuthProvider = ({ children }) => {
const [user, setUser] = useState(null); // 사용자 정보 상태 (null: 로그아웃 상태)
// 로그인 함수
const login = (userData) => {
setUser(userData); // 사용자 정보 설정
};
// 로그아웃 함수
const logout = () => {
setUser(null); // 사용자 정보 제거
};
return (
<AuthContext.Provider value={{ user, login, logout }}>
{children}
</AuthContext.Provider>
);
};
// Custom Hook for AuthContext
export const useAuth = () => useContext(AuthContext);
Context 여러 개 사용할 경우
CombinedProvider를 생성하여 여러 개의 Context Provider를 하나로 결합하여 사용할 수 있게 해주는 패턴을 적용
import React from "react";
import { AuthProvider } from "./AuthContext";
import { ModalProvider } from "./ModalContext";
const CombinedProvider = ({ children }) => {
return (
<ModalProvider>
<AuthProvider>
{children}
</AuthProvider>
</ModalProvider>
);
};
export default CombinedProvider;
import React, { useEffect } from 'react';
import CombinedProvider from './context/CombinedProvider';
const App = () => {
return (
<CombinedProvider>
<YourComponents />
</CombinedProvider>
);
}
export default App;
Custom Hook Example
import { useState, useEffect } from 'react';
function useLocalState(initialState, onStateChange) {
const [localStates, setLocalStates] = useState(initialState);
useEffect(() => {
if (onStateChange) {
onStateChange(localStates);
}
}, [localStates, onStateChange]);
const handleLocalStateChange = (value, stateName) => {
setLocalStates(prev => ({ ...prev, [stateName]: value }));
};
return [localStates, handleLocalStateChange, setLocalStates];
}
export default useLocalState;
Custom Hook 일괄 Export 적용시키기
일괄 export를 적용하여 import 할 때 경로를 간결하게 작성할 수 있으며 모든 커스텀 훅을 한 곳에서 관리할 수 있다.
index.js 생성
import useLocalState from "./useLocalState";
import useCustomHook1 from "./useCustomHook1";
import useCustomHook2 from "./useCustomHook2";
import useCustomHook3 from "./useCustomHook3";
...
export {
useLocalState,
useCustomHook1,
useCustomHook2,
useCustomHook3,
...
}
커스텀 훅 import
import { useLocalState, useCustomHook1, useCustomHook2 } from '../hooks';
앞에서 그냥 사용했던 useState, useEffect와 같은 Hook들이 어떤것인지 정리가 되었을 것이라 생각한다.
이전글
다음글
React axios 모듈화 (0) | 2025.02.07 |
---|---|
React-Router-Dom 정리 (0) | 2025.02.06 |
React CORS 설정 - 프록시 (http-proxy-middleware) (7) | 2025.01.31 |
React 설치 및 실행 / 프로젝트 구조 정리 (3) | 2025.01.30 |
React 기본 개념 정리 (5) | 2025.01.23 |
댓글 영역