전역 상태 관리

Yuno·2025년 4월 13일
0

React 정복하기

목록 보기
7/7

🤔 전역 상태가 필요한 이유?

React 에서 컴포넌트끼리 데이터를 공유하려면 props 로 계속 전달해야 함

하지만 컴포넌트가 많아지면..

<App>
  <Layout>
    <Header>
      <UserMenu user={user} />  ← props 넘기고 넘기고 넘기고...
    </Header>
  </Layout>
</App>
  • 그래서 모든 컴포넌트가 공유하는 상태는 "전역 상태 관리" 로 분리

🚀 Context API (React 기본 제공, 작은 프로젝트에 적합)

💡 로그인 사용자 정보 UserContext 로 관리

1️⃣ Context

// contexts/UserContext.tsx
import { createContext, ReactNode, useContext, useState } from "react";

type User = {
    id: number;
    name: string;
};

type UserContextType = {
    user: User | null;
    setUser: (user: User | null) => void;
};

const UserContext = createContext<UserContextType | undefined>(undefined);

export const UserProvider = ({ children }: { children: ReactNode }) => {
    const [user, setUser] = useState<User | null>(null);

    return (
        <UserContext.Provider value={{ user, setUser }}>
            {children}
        </UserContext.Provider>
    );
};

export const useUser = () => {
    const context = useContext(UserContext);
    if (!context) throw new Error('useUser 는 UserProvider 안에서만 사용하애 함');
    return context;
}

2️⃣ main.tsx 에서 전체 앱에 Provider로 감싸기

// main.tsx
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.tsx'
import React from 'react'
import { BrowserRouter } from 'react-router-dom'
import { UserProvider } from './contexts/UserContext.tsx'

createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <BrowserRouter>
      <UserProvider>
        <App />
      </UserProvider>
    </BrowserRouter>
  </React.StrictMode>
)

3️⃣ 테스트용 로그인 페이지 만들기

// pages/LoginPage.tsx
import { useUser } from "../contexts/UserContext";

function LoginPage() {
    const { setUser } = useUser();

    const handleLogin = () => {
        // 실제 로그인이라면 여기에 API 호출을 해야 함
        setUser({ id: 1, name: '유노' }); // 로그인 완료 처리
    };

    return (
        <div>
            <h2>로그인 페이지</h2>
            <button onClick={handleLogin}>로그인</button>
        </div>
    );
}

export default LoginPage;

4️⃣ 라우팅 추가

// App.tsx
import { Route, Routes } from "react-router-dom";
import HomePage from "./pages/HomePage";
import AboutPage from "./pages/AboutPage";
import Header from "./components/Header";
import UserPage from "./pages/UserPage";
import LoginPage from "./pages/LoginPage";

function App() {
  return (
    <>
      <Header />
      <Routes>
        <Route path="/" element={<HomePage />} />
        <Route path="/about" element={<AboutPage />} />
        <Route path="/user" element={<UserPage />} />
        <Route path="/login" element={<LoginPage />}/>
      </Routes>
    </>
  );
}

export default App;

5️⃣ 어디서든 사용자 상태 접근하기

// components/Header.tsx
import { Link } from "react-router-dom";
import { useUser } from "../contexts/UserContext";

function Header() {

    const { user, setUser } = useUser();
    return (
        <nav>
            <Link to="/"></Link> | <Link to="/about">소개</Link> | <Link to={"/user"}>유저 목록</Link> |
            {!user ? (
                <Link to={"/login"}>로그인</Link>
            ) : (
                <>
                    <span>{user.name}님 환영합니다</span>
                    <button onClick={() => setUser(null)}>로그아웃</button>
                </>
            )}
        </nav>
    );
}

export default Header;


🚀 핵심 요약

항목설명
Context컴포넌트 계층을 거치지 않고 전역으로 값 전달
useContext하위 컴포넌트에서 값 사용
Provider최상단에서 값 공급
작은 프로젝트Context API 만으로 충분
profile
Hello World

0개의 댓글