Props를 여러 단계로 전달하는 것은 번거롭다. Context를 사용하면 전역적으로 데이터를 공유할 수 있다.
function App() {
const [user, setUser] = useState('김철수');
return <Page user={user} />;
}
function Page({ user }) {
return <Header user={user} />;
}
function Header({ user }) {
return <Profile user={user} />;
}
function Profile({ user }) {
return <div>{user}</div>;
}
// user를 3단계나 전달해야 한다!
import { createContext } from 'react';
const UserContext = createContext();
function App() {
const [user, setUser] = useState('김철수');
return (
<UserContext.Provider value={user}>
<Page />
</UserContext.Provider>
);
}
import { useContext } from 'react';
function Profile() {
const user = useContext(UserContext);
return <div>{user}</div>;
}
import { createContext, useContext, useState } from 'react';
// Context 생성
const UserContext = createContext();
function App() {
const [user, setUser] = useState('김철수');
return (
<UserContext.Provider value={user}>
<Page />
</UserContext.Provider>
);
}
function Page() {
return (
<div>
<h1>페이지</h1>
<Profile />
</div>
);
}
function Profile() {
const user = useContext(UserContext);
return <div>사용자: {user}</div>;
}
객체를 사용하면 여러 값을 한 번에 전달할 수 있다.
const UserContext = createContext();
function App() {
const [user, setUser] = useState('김철수');
const [age, setAge] = useState(25);
return (
<UserContext.Provider value={{ user, age, setUser, setAge }}>
<Page />
</UserContext.Provider>
);
}
function Profile() {
const { user, age, setUser } = useContext(UserContext);
return (
<div>
<p>이름: {user}, 나이: {age}</p>
<button onClick={() => setUser('이영희')}>이름 변경</button>
</div>
);
}
Context를 별도 파일로 만들면 재사용하기 쉽다.
import { createContext, useState } from 'react';
export const UserContext = createContext();
export function UserProvider({ children }) {
const [user, setUser] = useState('김철수');
const [age, setAge] = useState(25);
return (
<UserContext.Provider value={{ user, age, setUser, setAge }}>
{children}
</UserContext.Provider>
);
}
import { UserProvider } from './UserContext';
function App() {
return (
<UserProvider>
<Page />
</UserProvider>
);
}
import { useContext } from 'react';
import { UserContext } from './UserContext';
function Profile() {
const { user, age } = useContext(UserContext);
return <div>{user}, {age}살</div>;
}
useContext를 감싸는 커스텀 훅을 만들면 더 편리하다.
// UserContext.jsx
import { createContext, useContext, useState } from 'react';
const UserContext = createContext();
export function UserProvider({ children }) {
const [user, setUser] = useState('김철수');
return (
<UserContext.Provider value={{ user, setUser }}>
{children}
</UserContext.Provider>
);
}
// Custom Hook
export function useUser() {
const context = useContext(UserContext);
if (!context) {
throw new Error('UserProvider 안에서 사용해야 합니다');
}
return context;
}
// 사용
function Profile() {
const { user, setUser } = useUser();
return <div>{user}</div>;
}
import { createContext, useContext, useState } from 'react';
const ThemeContext = createContext();
export function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
const toggle = () => {
setTheme(theme === 'light' ? 'dark' : 'light');
};
return (
<ThemeContext.Provider value={{ theme, toggle }}>
{children}
</ThemeContext.Provider>
);
}
export function useTheme() {
return useContext(ThemeContext);
}
// App.jsx
function App() {
return (
<ThemeProvider>
<Page />
</ThemeProvider>
);
}
function Page() {
const { theme, toggle } = useTheme();
const style = {
background: theme === 'light' ? '#fff' : '#333',
color: theme === 'light' ? '#000' : '#fff',
padding: '20px'
};
return (
<div style={style}>
<h1>현재 테마: {theme}</h1>
<button onClick={toggle}>테마 변경</button>
<Content />
</div>
);
}
function Content() {
const { theme } = useTheme();
return <p>{theme} 모드입니다.</p>;
}
import { createContext, useContext, useState } from 'react';
const CartContext = createContext();
export function CartProvider({ children }) {
const [items, setItems] = useState([]);
const add = (item) => {
setItems([...items, item]);
};
const remove = (id) => {
setItems(items.filter(item => item.id !== id));
};
return (
<CartContext.Provider value={{ items, add, remove }}>
{children}
</CartContext.Provider>
);
}
export function useCart() {
return useContext(CartContext);
}
// 사용
function ProductList() {
const { add } = useCart();
const products = [
{ id: 1, name: '사과', price: 1000 },
{ id: 2, name: '바나나', price: 1500 }
];
return (
<div>
{products.map(p => (
<div key={p.id}>
{p.name} - {p.price}원
<button onClick={() => add(p)}>담기</button>
</div>
))}
</div>
);
}
function Cart() {
const { items, remove } = useCart();
const total = items.reduce((sum, item) => sum + item.price, 0);
return (
<div>
<h2>장바구니</h2>
{items.map((item, i) => (
<div key={i}>
{item.name} - {item.price}원
<button onClick={() => remove(item.id)}>삭제</button>
</div>
))}
<p>총액: {total}원</p>
</div>
);
}
function App() {
return (
<CartProvider>
<ProductList />
<Cart />
</CartProvider>
);
}
function App() {
return (
<UserProvider>
<ThemeProvider>
<CartProvider>
<Page />
</CartProvider>
</ThemeProvider>
</UserProvider>
);
}
function Page() {
const { user } = useUser();
const { theme } = useTheme();
const { items } = useCart();
return (
<div>
<p>사용자: {user}</p>
<p>테마: {theme}</p>
<p>장바구니: {items.length}개</p>
</div>
);
}
createContext로 Context를 만든다