createContext는 컴포넌트들이 제공(provide)하거나 읽을 수 있는 컨텍스트(context)를 만들어주는 함수예요.
const SomeContext = createContext(defaultValue)
createContext(defaultValue) {/createcontext/}컨텍스트를 만들려면 컴포넌트 바깥에서 createContext를 호출하면 돼요.
// 예시
import { createContext } from 'react';
const ThemeContext = createContext('light');
defaultValue: 컨텍스트를 읽는 컴포넌트 위쪽 트리에 일치하는 컨텍스트 프로바이더(provider)가 없을 때, 컨텍스트가 가지길 원하는 값이에요. 만약 의미 있는 기본값이 없다면, null을 지정하면 돼요. 기본값은 "최후의 수단"으로서의 폴백(fallback) 역할을 하는 거예요. 이 값은 정적(static)이고 시간이 지나도 절대 바뀌지 않아요.createContext는 컨텍스트 객체를 반환해요.
컨텍스트 객체 자체는 어떤 정보도 담고 있지 않아요. 이 객체는 다른 컴포넌트들이 읽거나 제공하는 어떤 컨텍스트인지를 나타내는 거예요. 일반적으로, 상위 컴포넌트에서 SomeContext를 사용해서 컨텍스트 값을 지정하고, 하위 컴포넌트에서 useContext(SomeContext)를 호출해서 그 값을 읽는 방식으로 사용해요. 컨텍스트 객체에는 몇 가지 속성이 있어요:
SomeContext를 사용하면 컴포넌트들에게 컨텍스트 값을 제공할 수 있어요.SomeContext.Consumer는 컨텍스트 값을 읽는 대안적인 방법인데, 거의 사용되지 않아요.SomeContext.Provider는 React 19 이전에 컨텍스트 값을 제공하던 레거시(legacy) 방식이에요.SomeContext 프로바이더 (Provider) {/provider/}컴포넌트를 컨텍스트 프로바이더로 감싸면, 그 안에 있는 모든 컴포넌트에 대해 이 컨텍스트의 값을 지정할 수 있어요:
function App() {
const [theme, setTheme] = useState('light');
// ...
return (
<ThemeContext value={theme}>
<Page />
</ThemeContext>
);
}
참고
React 19부터는
<SomeContext>를 프로바이더로 렌더링할 수 있어요.이전 버전의 React에서는
<SomeContext.Provider>를 사용해야 해요.
value: 이 프로바이더 안에서 이 컨텍스트를 읽는 모든 컴포넌트에 전달하고 싶은 값이에요. 얼마나 깊이 중첩되어 있든 상관없어요. 컨텍스트 값은 어떤 타입이든 될 수 있어요. 프로바이더 안에서 useContext(SomeContext)를 호출하는 컴포넌트는 그 위에 있는 가장 가까운(innermost) 해당 컨텍스트 프로바이더의 value를 받게 돼요.SomeContext.Consumer {/consumer/}useContext가 존재하기 전에는, 컨텍스트를 읽는 오래된 방법이 있었어요:
function Button() {
// 🟡 레거시 방식 (권장하지 않음)
return (
<ThemeContext.Consumer>
{theme => (
<button className={theme} />
)}
</ThemeContext.Consumer>
);
}
이 오래된 방식은 여전히 동작하긴 하지만, 새로 작성하는 코드에서는 useContext()를 사용해서 컨텍스트를 읽는 것을 권장해요:
function Button() {
// ✅ 권장하는 방식
const theme = useContext(ThemeContext);
return <button className={theme} />;
}
children: 함수예요. React는 여러분이 전달한 함수를 useContext()와 동일한 알고리즘으로 결정된 현재 컨텍스트 값과 함께 호출하고, 이 함수에서 반환한 결과를 렌더링해요. 부모 컴포넌트에서 컨텍스트가 변경될 때마다 React는 이 함수를 다시 실행하고 UI를 업데이트해요.컨텍스트를 사용하면 컴포넌트들이 props를 명시적으로 전달하지 않고도 정보를 깊숙이 전달할 수 있어요.
하나 이상의 컨텍스트를 만들려면 컴포넌트 바깥에서 createContext를 호출하면 돼요.
import { createContext } from 'react';
const ThemeContext = createContext('light');
const AuthContext = createContext(null);
createContext는 컨텍스트 객체를 반환해요. 컴포넌트에서 컨텍스트를 읽으려면 useContext()에 해당 컨텍스트를 전달하면 돼요:
function Button() {
const theme = useContext(ThemeContext);
// ...
}
function Profile() {
const currentUser = useContext(AuthContext);
// ...
}
기본적으로, 컴포넌트들이 받는 값은 컨텍스트를 만들 때 지정한 기본값(default values)이에요. 하지만 기본값은 절대 변하지 않기 때문에, 이것만으로는 그다지 유용하지 않아요.
컨텍스트가 유용한 이유는 컴포넌트에서 다른, 동적인 값을 제공할 수 있기 때문이에요:
function App() {
const [theme, setTheme] = useState('dark');
const [currentUser, setCurrentUser] = useState({ name: 'Taylor' });
// ...
return (
<ThemeContext value={theme}>
<AuthContext value={currentUser}>
<Page />
</AuthContext>
</ThemeContext>
);
}
이제 Page 컴포넌트와 그 안에 있는 모든 컴포넌트들은, 아무리 깊이 중첩되어 있더라도, 전달된 컨텍스트 값을 "볼 수" 있게 돼요. 전달된 컨텍스트 값이 변경되면, React는 해당 컨텍스트를 읽는 컴포넌트들도 함께 다시 렌더링해줘요.
컨텍스트 읽기와 제공하기에 대한 자세한 내용과 예제는 여기서 확인하세요.
종종 다른 파일에 있는 컴포넌트들이 같은 컨텍스트에 접근해야 할 때가 있어요. 그래서 별도의 파일에 컨텍스트를 선언하는 게 일반적이에요. 그런 다음 export 문을 사용해서 다른 파일에서 컨텍스트를 사용할 수 있게 만들면 돼요:
// Contexts.js
import { createContext } from 'react';
export const ThemeContext = createContext('light');
export const AuthContext = createContext(null);
다른 파일에서 선언된 컴포넌트들은 import 문을 사용해서 이 컨텍스트를 읽거나 제공할 수 있어요:
// Button.js
import { ThemeContext } from './Contexts.js';
function Button() {
const theme = useContext(ThemeContext);
// ...
}
// App.js
import { ThemeContext, AuthContext } from './Contexts.js';
function App() {
// ...
return (
<ThemeContext value={theme}>
<AuthContext value={currentUser}>
<Page />
</AuthContext>
</ThemeContext>
);
}
이건 컴포넌트를 가져오고 내보내는 것과 비슷한 방식으로 동작해요.
이런 코드는 기본 컨텍스트 값을 지정하는 거예요:
const ThemeContext = createContext('light');
이 값은 절대 변하지 않아요. React는 위에서 일치하는 프로바이더를 찾을 수 없을 때만 이 값을 폴백(fallback)으로 사용해요.
시간에 따라 컨텍스트가 변하게 만들려면, 상태(state)를 추가하고 컴포넌트를 컨텍스트 프로바이더로 감싸세요.