React 함수를 Context API로 관리하여 prop drilling없애기

장현빈·2025년 2월 7일

1️⃣ Context API란?

  • React.createContext()를 사용하여 전역적으로 상태를 관리할 수 있는 기능
  • useContext()를 통해 쉽게 값을 가져올 수 있음
  • Redux 같은 상태 관리 라이브러리 없이도 전역 상태 관리가 가능

2️⃣ 사용 방법

    1. Context 생성
import { createContext } from "react";
export const ThemeContext = createContext(null);
    1. 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;
    1. 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와 비교하여 간단한 상태 관리에 적합

Pokemon project에 적용하기 !

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 적용

    1. App.js에서 PokemonProvider로 감싸기
import { PokemonProvider } from "./PokemonContext";
function App() {
  return (
    <PokemonProvider>
      <Dashboard />
      <Dex />
    </PokemonProvider>
  );
}
export default App;
    1. 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>;
};
    1. 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를 함께 사용하면 더 효율적일 듯
profile
안녕하세요

0개의 댓글