함수형 컴포넌트 정의
function MyComponent() {
return <div>Hello!</div>;
}
또는
const MyComponent = () => {
return <div>Hello!</div>;
};
React에선 함수형 컴포넌트를 더 많이 씁니다. 화살표 함수도 가능합니다.
컴포넌트는 <MyComponent />처럼 사용
불필요한 <div> 대신 <></> 사용 가능
return (
<>
<Header />
<Content />
</>
);
<></>는React.Fragment의 축약형입니다. DOM 구조가 깔끔해집니다.
컴포넌트는 순수 함수(Pure Function)처럼 동작해야 합니다.
같은 props가 들어가면 항상 같은 결과를 반환해야 해요.
📦 주의
A 컴포넌트의 state는 B 컴포넌트에서 직접 사용할 수 없습니다. 예:
const Parent = () => {
const [count, setCount] = useState(0);
return <Child />; // count 전달 안 됨
};
상태 공유가 필요하다면 props, context, redux 등을 사용해야 합니다.
useEffect(() => {
console.log("마운트 시 실행");
}, []);
[]를 전달하면 마운트될 때 한 번만 실행됩니다.
🧠 실행 타이밍 이해하기:
📦 주의
| Hook | 반환값 | 사용 목적 | 예시 |
|---|---|---|---|
useMemo | 계산된 값 | 무거운 계산 결과 재사용 | const value = useMemo(() => calc(a), [a]) |
useCallback | 함수 | 동일한 함수 객체 유지 | const onClick = useCallback(() => doSomething(), [deps]) |
📦 주의
useMemo는 값 메모이제이션, useCallback은 함수 메모이제이션입니다.const inputRef = useRef(null);
const handleFocus = () => {
inputRef.current.focus();
};
return <input ref={inputRef} />;
📌 설명
useRef는 DOM에 직접 접근하거나, 렌더링에 영향을 주지 않는 값 저장에 적합합니다.const reducer = (state, action) => {
switch (action.type) {
case "increment": return { count: state.count + 1 };
case "decrement": return { count: state.count - 1 };
default: throw new Error("Unknown action");
}
};
const [state, dispatch] = useReducer(reducer, { count: 0 });
🆚 비교표
| 항목 | useReducer | useState |
|---|---|---|
| 목적 | 복잡한 상태 로직 | 단순 상태 |
| 구조 | reducer 함수로 처리 | 직접 setState |
| 적합한 상황 | 여러 상태 묶기 | 단일 값 처리 |
📦 주의
const MyContext = React.createContext();
const value = useContext(MyContext);
🆚 비교
| 항목 | Props | useContext |
|---|---|---|
| 구조 | 부모 → 자식 단방향 | 어디서든 접근 가능 |
| 성능 | 변경된 부분만 렌더 | 연결된 컴포넌트 모두 렌더링 |
📦 주의
| 단계 | useLayoutEffect | useEffect |
|---|---|---|
| 실행 시점 | DOM 적용 직후, 화면 그리기 전 | 화면 그린 후 |
| 적합한 작업 | DOM 조작, 스타일 측정 | 비동기 요청, 상태 처리 |
| 깜빡임 방지 | ✅ | ❌ |
📦 주의
useLayoutEffect는 동기적으로 실행되므로 UI가 멈출 수 있습니다. DOM 조작 용도로만 사용하세요.function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
return width;
}
📌 설명
useState, useEffect, 등)을 조합해 복잡한 로직을 공통화할 수 있습니다.무조건 최상위 레벨에서 호출할 것
if (condition) {
useEffect(() => {}, []); // ❌ 이렇게 하면 안됨
}
매 렌더링마다 Hook 호출 순서가 달라지면 React 내부 상태가 꼬입니다.
React 함수 컴포넌트나 Custom Hook 안에서만 호출할 것
일반 함수나 조건문, 루프에서는 절대 호출하지 마세요.
조건부 렌더링: isVisible && <Component /> 또는 삼항 연산자 condition ? A : B
리스트 렌더링: map() 사용 + 고유한 key 필요
select 박스: value 바인딩 필요, 다중 선택은 multiple={true} + 배열
<select value={selectedValue} onChange={handleChange}>
<option value="a">A</option>
</select>
이벤트 핸들러 기본 구조
const handleChange = (event) => {
setValue(event.target.value);
};
📌 event 구조 요약
event: 이벤트 객체event.target: 이벤트 발생 요소event.target.value: 해당 요소의 value 값const MyContext = createContext();
const Parent = () => {
const contextValue = { message: "Hello" };
return (
<MyContext.Provider value={contextValue}>
<Child />
</MyContext.Provider>
);
};
📦 주의
value에 객체, 배열, 함수 리터럴 등 매번 새로 생성되는 값을 전달하면 Provider가 매 렌더링마다 새로운 참조를 전달하게 되어, 모든 하위 컴포넌트가 리렌더링됩니다.✅ 해결 방법:
const contextValue = useMemo(() => ({ message: "Hello" }), []);
useMemo를 이용해 참조값을 유지하면 불필요한 리렌더링을 방지할 수 있습니다.
import { BrowserRouter, Routes, Route } from "react-router-dom";
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</BrowserRouter>
📌 설명
BrowserRouter는 HTML5 History API를 활용해 페이지 전체 새로고침 없이 URL을 변경해주는 컴포넌트입니다.import { lazy, Suspense } from "react";
import LoadingSpinner from "./LoadingSpinner";
const OtherComponent = lazy(() => import("./OtherComponent"));
function MyComponent() {
return (
<Suspense fallback={<LoadingSpinner />}>
<OtherComponent />
</Suspense>
);
}
📌 설명
Suspense는 lazy 로딩된 컴포넌트가 로드되기 전까지 대기 상태를 표시합니다.fallback에 로딩 컴포넌트(예: Spinner)를 지정해 사용자 경험을 개선합니다.📦 주의
Suspense는 lazy()와 함께 사용할 때만 동작합니다.| 항목 | Link 방식 | useNavigate 방식 |
|---|---|---|
| 사용 방식 | 정적 이동 (클릭 기반) | 동적 이동 (로직 기반) |
| 예시 | 메뉴, 리스트 항목 등 | 조건 분기, API 후 이동 |
| URL 변경 | 사용자가 클릭해야 발생 | 함수 호출로 발생 |
| 뒤로 가기 지원 | ❌ (Link 자체로는 불가능) | ✅ (navigate(-1)) |
✅ 추천 사용처
LinkuseNavigate()// Link 사용
<Link to="/home">Home</Link>
// useNavigate 사용
const navigate = useNavigate();
navigate("/home");
📦 주의
useNavigate()는 react-router-dom의 훅이며, 컴포넌트 내에서만 호출 가능합니다.