1️⃣ Context API란?
- React.createContext()를 사용하여 전역적으로 상태를 관리할 수 있는 기능
- useContext()를 통해 쉽게 값을 가져올 수 있음
- Redux 같은 상태 관리 라이브러리 없이도 전역 상태 관리가 가능
2️⃣ 사용 방법
- Context 생성
import { createContext } from "react"; export const ThemeContext = createContext(null);
- Provider 설정 (전역 상태 공유)
import { ThemeContext } from "./ThemeContext"; const ThemeProvider = ({ children }) => { const [theme, setTheme] = useState("light"); return ( <ThemeContext.Provider value={{ theme, setTheme }}> {children} </ThemeContext.Provider> ); }; export default ThemeProvider;
- Context 사용
import { useContext } from "react"; import { ThemeContext } from "./ThemeContext"; const ThemeSwitcher = () => { const { theme, setTheme } = useContext(ThemeContext); return ( <button onClick={() => setTheme(theme === "light" ? "dark" : "light")}> Toggle Theme </button> ); };
3️⃣ Context API 사용 시 고려할 점
✅ 전역 상태가 많아지면 성능 이슈 발생 가능 → 불필요한 리렌더링 주의
✅ 비효율적인 상태 업데이트 방지 → useMemo, useCallback 활용
✅ Redux와 비교하여 간단한 상태 관리에 적합
1️⃣ PokemonContext 적용
목표:
- PokemonContext를 만들어 addPokemon, removePokemon 함수를 전역에서 관리
- Dashboard.jsx, Dex.jsx 등의 컴포넌트에서 props 없이 포켓몬 추가/삭제 가능
2️⃣ Context 생성 및 Provider 설정
import { createContext, useState, useContext } from "react"; // 1. Context 생성 const PokemonContext = createContext(); // 2. Provider 설정 export const PokemonProvider = ({ children }) => { const [pokemonList, setPokemonList] = useState([]); const addPokemon = (pokemon) => { setPokemonList((prevList) => [...prevList, pokemon]); }; const removePokemon = (id) => { setPokemonList((prevList) => prevList.filter((p) => p.id !== id)); }; return ( <PokemonContext.Provider value={{ pokemonList, addPokemon, removePokemon }}> {children} </PokemonContext.Provider> ); }; // 3. Context 사용 훅 생성 (편의성) export const usePokemon = () => useContext(PokemonContext);
3️⃣ Context 적용
- App.js에서 PokemonProvider로 감싸기
import { PokemonProvider } from "./PokemonContext"; function App() { return ( <PokemonProvider> <Dashboard /> <Dex /> </PokemonProvider> ); } export default App;
- Dashboard.jsx에서 포켓몬 추가 기능 사용
import { usePokemon } from "./PokemonContext"; const Dashboard = () => { const { addPokemon } = usePokemon(); const handleAddPokemon = () => { const newPokemon = { id: Date.now(), name: "Pikachu" }; addPokemon(newPokemon); }; return <button onClick={handleAddPokemon}>포켓몬 추가</button>; };
- Dex.jsx에서 포켓몬 목록과 삭제 기능 사용
import { usePokemon } from "./PokemonContext"; const Dex = () => { const { pokemonList, removePokemon } = usePokemon(); return ( <div> {pokemonList.map((pokemon) => ( <div key={pokemon.id}> <span>{pokemon.name}</span> <button onClick={() => removePokemon(pokemon.id)}>삭제</button> </div> ))} </div> ); };
4️⃣ Context API를 적용한 후의 변화
✅ props 없이 전역에서 상태 관리 가능
✅ addPokemon, removePokemon을 어디서든 쉽게 호출 가능
✅ 코드 구조가 더 간결해지고 유지보수가 편리해짐
💡 오늘의 결론:
- Context API를 활용하면 props drilling 없이 전역 상태 관리 가능
- useContext를 커스텀 훅(usePokemon)으로 만들어 코드 가독성을 높일 수 있음
- 상태 변경이 복잡해질 경우 useReducer를 함께 사용하면 더 효율적일 듯