Context는 맥락을 의미하며, 상황에 대한 정보를 의미한다. 즉, 많은 컴포넌트에서 사용하는 데이터를 반복적인 Prop 전달(Prop Drilling) 없이 공유할 때 사용한다.
import { createContext } from 'react';
const LocaleContext = createContext();
export default LocaleContext;
// App.js
return (
<LocaleContext.Provider value="ko">
<div>
<div>
<button onClick={handleNewestClick}>최신순</button>
<button onClick={handleBestClick}>베스트순</button>
</div>
<ReviewForm
onSubmit={createReview}
onSubmitSuccess={handleCreateSuccess}
/>
<ReviewList
items={sortedItems}
onDelete={handleDelete}
onUpdate={updateReview}
onUpdateSuccess={handleUpdateSuccess}
/>
{hasNext && (
<button disabled={isLoading} onClick={handleLoadMore}>
더 보기
</button>
)}
{loadingError?.message && <span>{loadingError.message}</span>}
</div>
</LocaleContext.Provider>
);
// ReviewList.js
function ReviewListItem({ item, onDelete, onEdit }) {
const locale = useContext(LocaleContext);
function LocaleSelect({ value, onChange}) {
const handleChange = (e) => onChange(e.target.value);
return (
<select value={value} onChange={handleChange}>
<option value="ko">한국어</option>
<option value="en">English</option>
</select>
);
}
export default LocaleSelect;
// App.js
const [locale, setLocale] = useState('ko');
...
<LocaleContext.Provider value={locale}>
<div>
<LocaleSelect value={locale} onChange={setLocale} />
import { createContext, useContext, useState } from 'react';
const LocaleContext = createContext();
export function LocaleProvider({ defaultValue = 'ko', children }) {
const [locale, setLocale] = useState(defaultValue);
return (
<LocaleContext.Provider value={{ locale, setLocale }}>
{children}
</LocaleContext.Provider>
);
}
export function useLocale() {
const context = useContext(LocaleContext);
if (!context) {
throw new Error('반드시 LocaleProvider 안에서 사용해야 합니다');
}
const { locale } = context;
return locale;
}
export function useSetLocale() {
const context = useContext(LocaleContext);
if (!context) {
throw new Error('반드시 LocaleProvider 안에서 사용해야 합니다');
}
const { setLocale } = context;
return setLocale;
}
import { useLocale } from '../contexts/LocaleContext';
const dict = {
ko: {
'confirm button': '확인',
'cancel button': '취소',
'edit button': '수정',
'delete button': '삭제',
},
en: {
'confirm button': 'OK',
'cancel button': 'Cancel',
'edit button': 'Edit',
'delete button': 'Delete',
},
};
function useTranslate() {
const locale = useLocale();
const translate = (key) => dict[locale][key] || '';
return translate;
}
export default useTranslate;
Context는 한국어로 맥락이라는 뜻이다. 쉽게 말해서 어떤 상황에 대한 정보를 의미한다. '사용자가 한국어를 사용하는 상황', '사용자가 영어를 사용하는 상황' 같은 걸 여러 컴포넌트에 공유하고 싶을 때 사용한다. 컴포넌트의 단계가 많다면 여러 번 반복해서 Prop을 내려줘야 하는 문제점이 있는데 이를 프롭 드릴링(Prop Drilling)이라고 한다.
Context는 createContext라는 함수를 통해 만들 수 있다.
import { createContext } from 'react';
const LocaleContext = createContext();
기본값을 넣어줄 수도 있다.
import { createContext } from 'react';
const LocaleContext = createContext('ko');
Context를 쓸 때는 반드시 값을 공유할 범위를 정하고 써야 한다. 이때 범위는 Context 객체에 있는 Provider라는 컴포넌트로 정해줄 수 있다. 이때 Provider의 value prop으로 공유할 값을 내려주면 된다.
import { createContext } from 'react';
const LocaleContext = createContext('ko');
function App() {
return (
<div>
... 바깥의 컴포넌트에서는 LocaleContext 사용불가
<LocaleContext.Provider value="en">
... Provider 안의 컴포넌트에서는 LocaleContext 사용가능
</LocaleContext.Provider>
</div>
);
}
useContext라는 Hook을 사용하면 값을 가져와 사용할 수 있다. 이때 아규먼트로 사용할 Context를 넘겨주면 된다.
import { createContext, useContext } from 'react';
const LocaleContext = createContext('ko');
function Board() {
const locale = useContext(LocaleContext);
return <div>언어: {locale}</div>;
}
function App() {
return (
<div>
<LocaleContext.Provider value="en">
<Board />
</LocaleContext.Provider>
</div>
);
}
Provider 역할을 하는 컴포넌트를 하나 만들고, 여거시 State를 만들어서 value로 넘겨줄 수 있다. 그리고 아래의 useLocale 같이 useContext를 사용해서 값을 가져오는 커스텀 Hook을 만들 수 있다. 이렇게 하면 Context에서 사용하는 State 값은 반드시 우리가 만든 함수를 통해서만 쓸 수 있기 때문에 안전한 코드를 작성하는데 도움이 된다.
import { createContext, useContext, useState } from 'react';
const LocaleContext = createContext({});
export function LocaleProvider({ children }) {
const [locale, setLocale] = useState();
return (
<LocaleContext.Provider value={{ locale, setLocale }}>
{children}
</LocaleContext.Provider>
);
}
export function useLocale() {
const context = useContext(LocaleContext);
if (!context) {
throw new Error('반드시 LocaleProvider 안에서 사용해야 합니다');
}
const { locale } = context;
return locale;
}
export function useSetLocale() {
const context = useContext(LocaleContext);
if (!context) {
throw new Error('반드시 LocaleProvider 안에서 사용해야 합니다');
}
const { setLocale } = context;
return setLocale;
}
상태 관리(State Management)란, 화면에서 사용하는 데이터를 관리하는 것을 의미한다.
Flux : 데이터의 변경을 한 곳에서 하면서 흐름을 정리
Recoil : 전역적으로 쓸 수 있는 useState