useState
는 함수형 컴포넌트에서 상태를 관리할 수 있게 해주고, 가장 기본적인 Hook입니다. 이를 사용하면 클래스 컴포넌트를 사용하지 않고도 상태를 가질 수 있습니다. useState
는 초기 상태 값을 인자로 받아 상태 변수와 상태 변경 함수를 반환합니다.
import React, { useState } from 'react';
function Counter() {
// count 상태 변수 선언, 초기 값은 0
const [count, setCount] = useState(0);
// 버튼 클릭 시 호출되는 함수
const increment = () => {
// count 상태를 현재 값 + 1로 업데이트
setCount(count + 1);
};
return (
<div>
{/* 현재 카운트 값을 표시 */}
<p>현재 카운트: {count}</p>
{/* 버튼을 클릭하면 increment 함수 호출 */}
<button onClick={increment}>카운트 증가</button>
</div>
);
}
export default Counter;
useEffect
는 React 함수형 컴포넌트에서 사이드 이펙트를 수행할 수 있게 해주는 Hook입니다. 이를 통해 컴포넌트가 마운트, 업데이트, 언마운트될 때 특정 작업을 수행할 수 있습니다. useEffect
는 두 개의 인자를 받습니다. 첫 번째 인자는 실행할 함수, 두 번째 인자는 의존성 배열입니다.
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0); // count 상태 변수 선언, 초기 값은 0
useEffect(() => {
// 컴포넌트가 마운트될 때 실행
console.log('컴포넌트가 마운트되었습니다.');
// 컴포넌트가 언마운트될 때 실행되는 정리 함수
return () => {
console.log('컴포넌트가 언마운트되었습니다.');
};
}, []); // 빈 배열을 전달하여 컴포넌트가 마운트될 때 한 번만 실행
const increment = () => {
setCount(count + 1); // count 상태를 현재 값 + 1로 업데이트
};
return (
<div>
<p>현재 카운트: {count}</p> {/* 현재 카운트 값을 표시 */}
<button onClick={increment}>카운트 증가</button> {/* 버튼을 클릭하면 increment 함수 호출 */}
</div>
);
}
export default Example;
useState(0)
: count
상태 변수 선언, 초기 값은 0.useEffect(() => { ... }, [])
: 컴포넌트가 마운트될 때와 언마운트되기 전이나 업데이트되기 직전에 특정 작업을 수행.increment
함수: 버튼 클릭 시 count 상태를 1씩 증가.useEffect
는 기본적으로 렌더링된 직후에 실행되며, 두 번째 파라미터 배열에 의존성을 넣으면 해당 의존성 값이 변경될 때마다 실행됩니다. 정리(cleanup) 함수는 컴포넌트가 언마운트되기 전이나 업데이트되기 직전에 실행됩니다.useReducer
는 상태 관리 로직이 복잡해질 때 유용한 React Hook입니다. useState
대신에 사용할 수 있으며, Redux와 같은 상태 관리 라이브러리와 유사한 패턴을 제공합니다.useReducer
는 세 가지 인자를 받습니다: 리듀서 함수, 초기 상태, (선택적) 초기화 함수입니다. 리듀서 함수는 현재 상태와 액션을 받아 새로운 상태를 반환합니다.
import React, { useReducer } from 'react';
// 리듀서 함수: 현재 상태와 액션을 받아 새로운 상태를 반환합니다.
function reducer(state, action) {
switch (action.type) {
case 'increment':
// count 상태를 1 증가시킵니다.
return { count: state.count + 1 };
case 'decrement':
// count 상태를 1 감소시킵니다.
return { count: state.count - 1 };
default:
throw new Error();
}
}
function Counter() {
// useReducer 사용: 리듀서 함수와 초기 상태를 전달하여 state와 dispatch를 반환합니다.
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<div>
{/* 현재 카운트 값을 표시합니다. */}
<p>현재 카운트: {state.count}</p>
{/* 버튼을 클릭하면 'increment' 액션을 디스패치합니다. */}
<button onClick={() => dispatch({ type: 'increment' })}>카운트 증가</button>
{/* 버튼을 클릭하면 'decrement' 액션을 디스패치합니다. */}
<button onClick={() => dispatch({ type: 'decrement' })}>카운트 감소</button>
</div>
);
}
export default Counter;
state
state
는 현재 컴포넌트의 상태 값을 나타냅니다.useReducer
에 의해 관리되는 상태는 단일 객체로 표현될 수 있으며, 이 객체는 리듀서 함수에 의해 업데이트됩니다.state
는 { count: 0 }
와 같은 형태로 초기화됩니다.dispatch
dispatch
는 액션을 리듀서 함수로 보내는 함수입니다.dispatch
를 호출하면, 리듀서 함수가 실행되어 현재 상태와 액션을 기반으로 새로운 상태를 반환합니다.useReducer를 이용한 여러개의 Inpunt상태 관리
import React, { useReducer } from 'react';
// 리듀서 함수: 현재 상태와 액션을 받아 새로운 상태를 반환합니다.
function reducer(state, action) {
switch (action.type) {
case 'setInput':
// 특정 필드의 값을 업데이트합니다.
return { ...state, [action.name]: action.value };
default:
// 정의되지 않은 액션 타입에 대한 에러를 던집니다.
console.error('처리되지 않은 액션 타입:', action.type);
throw new Error('처리되지 않은 액션 타입: ' + action.type);
}
}
function InputExample() {
// useReducer 사용: 리듀서 함수와 초기 상태를 전달하여 state와 dispatch를 반환합니다.
const [state, dispatch] = useReducer(reducer, { name: '', age: '', email: '' });
// 인풋 필드 값이 변경될 때 호출되는 함수
const handleChange = (e) => {
dispatch({ type: 'setInput', name: e.target.name, value: e.target.value });
};
return (
<div>
{/* 이름 인풋 필드 */}
<input
type="text"
name="name"
value={state.name}
onChange={handleChange}
placeholder="이름을 입력하세요"
/>
{/* 나이 인풋 필드 */}
<input
type="text"
name="age"
value={state.age}
onChange={handleChange}
placeholder="나이를 입력하세요"
/>
{/* 이메일 인풋 필드 */}
<input
type="email"
name="email"
value={state.email}
onChange={handleChange}
placeholder="이메일을 입력하세요"
/>
{/* 현재 인풋 필드의 값을 표시합니다. */}
<p>현재 입력 값: 이름: {state.name}, 나이: {state.age}, 이메일: {state.email}</p>
</div>
);
}
export default InputExample;
useMemo
를 사용하면 함수 컴포넌트 내부에서 발생하는 연산을 최적화할 수 있습니다. useMemo
는 성능 최적화를 위해 값이 변경되지 않는 한 계산을 다시 하지 않도록 하는 React Hook입니다. 주로 계산 비용이 높은 작업이나 렌더링 중에 반복적으로 실행될 수 있는 작업을 최적화하는 데 사용됩니다.
import React, { useState, useMemo } from "react";
const UseMemoSample = () => {
// 두 개의 상태 변수 선언: numbers와 inputValue
const [numbers, setNumbers] = useState([]);
const [inputValue, setInputValue] = useState("");
// numbers 배열이 변경될 때만 계산되는 평균값
const average = useMemo(() => {
console.log("평균값 계산 중...");
if (numbers.length === 0) return 0;
const sum = numbers.reduce((a, b) => a + b, 0);
return sum / numbers.length;
}, [numbers]);
// inputValue가 변경될 때 호출되는 함수
const handleInputChange = (e) => {
setInputValue(e.target.value);
};
// 새로운 숫자를 추가하는 함수
const addNumber = () => {
const number = parseFloat(inputValue);
setNumbers([...numbers, number]);
setInputValue("");
};
return (
<div>
{/* 숫자를 추가하는 인풋 필드와 버튼 */}
<input
type="text"
value={inputValue}
onChange={handleInputChange}
placeholder="숫자를 입력하세요"
/>
<button onClick={addNumber}>숫자 추가</button>
{/* 현재 numbers 배열의 값을 표시 */}
<p>입력된 숫자: {numbers.join(", ")}</p>
<p>평균값: {average}</p>
</div>
);
};
export default UseMemoSample;
useMemo
는 두 번째 인자인 의존성 배열의 값이 변경될 때만 첫 번째 인자로 전달된 함수가 실행되어 값을 다시 계산합니다. 이를 통해 불필요한 계산을 방지하고 성능을 최적화할 수 있습니다.count
가 변경될 때만 memoizedValue
가 다시 계산되며, inputValue
는 count
와 독립적으로 관리됩니다.useCallback
은 함수형 컴포넌트에서 함수를 메모이제이션하는 데 사용됩니다. 특정 의존성 배열이 변경되지 않는 한 함수를 새로 생성하지 않고 이전에 생성된 함수를 재사용합니다. 이는 자식 컴포넌트에 콜백 함수를 props로 전달할 때 특히 유용하며, 불필요한 렌더링을 방지하여 성능을 최적화할 수 있습니다.다.
import React, { useState, useCallback } from 'react';
// List 컴포넌트: 리스트 아이템을 표시하며, 각 아이템을 클릭할 때 onItemClick 함수를 호출합니다.
const List = ({ items, onItemClick }) => {
console.log('List 컴포넌트가 렌더링되었습니다.');
return (
<ul>
{items.map((item, index) => (
<li key={index} onClick={() => onItemClick(item)}>
{item}
</li>
))}
</ul>
);
};
const UseCallbackSample = () => {
// 두 개의 상태 변수 선언: count와 items
const [count, setCount] = useState(0);
const [items] = useState(['아이템1', '아이템2', '아이템3']);
// onItemClick 함수는 count가 변경될 때만 새로 생성됩니다.
const onItemClick = useCallback((item) => {
console.log(`${item}이 클릭되었습니다.`);
}, [count]);
return (
<div>
<p>카운트: {count}</p>
{/* 버튼을 클릭할 때 count 상태를 1 증가시킵니다. */}
<button onClick={() => setCount(count + 1)}>카운트 증가</button>
{/* List 컴포넌트에 items와 onItemClick을 props로 전달합니다. */}
<List items={items} onItemClick={onItemClick} />
</div>
);
};
export default UseCallbackSample;
useRef
는 함수형 컴포넌트에서 레퍼런스를 생성하는 데 사용됩니다. useRef
로 생성된 객체는 컴포넌트의 생명주기 동안 유지되며, 값이 변경되어도 리렌더링을 일으키지 않습니다. 주로 DOM 요소에 접근하거나 이전 값을 저장하는 데 사용됩니다. 예를 들어, input 요소에 포커스를 설정하거나, 이전 값을 저장하여 비교하는 데 유용합니다.
import React, { useRef } from 'react';
const UseRefSample = () => {
// inputRef는 input 요소를 참조합니다. 초기 값은 null입니다.
const inputRef = useRef(null);
// focusInput 함수는 버튼 클릭 시 input 요소에 포커스를 설정합니다.
const focusInput = () => {
// inputRef.current를 통해 input 요소에 접근하여 포커스를 설정합니다.
inputRef.current.focus();
};
return (
<div>
{/* inputRef를 input 요소에 연결합니다. */}
<input ref={inputRef} type="text" placeholder="여기에 입력하세요" />
{/* 버튼을 클릭할 때 focusInput 함수를 호출합니다. */}
<button onClick={focusInput}>포커스 설정</button>
</div>
);
};
export default UseRefSample;
이 예제는 useRef
를 사용하여 input
요소에 접근하고 포커스를 설정하는 방법을 보여줍니다. useRef
의 주요 장점은 컴포넌트의 생명주기 동안 레퍼런스를 유지하면서도 값이 변경되어도 리렌더링을 일으키지 않는다는 점입니다. 이는 DOM
요소에 직접 접근하거나 이전 값을 저장하여 비교할 때 매우 유용합니다.