로그인 데이터, 웹 내 사용자가 쓰는 설정파일, 테마, 언어, nav에서 로그인된 상태의 화면등 context를 사용하면 편리하게 코드를 관리할 수 있다.
리액트 패키지에서 createContext
함수를 불러와서 변수에 담고 인자로 기본값을 준다.
import { createContext } from 'react';
const MyContext = createContext();
Context 객체 안에는 Provider라는 이름의 컴포넌트가 들어있다. 그 컴포넌트간에 공유하고자 하는 값을 value
라는 Props로 설정하면 자식 컴포넌트들에서 해당 값에 바로 접근할 수 있다.
Context에 저장된 데이터를 사용하기 위해서는 공통 부모 컴포넌트에 Context의 Provider를 사용하여 데이터를 제공해야 한다.
function App() {
return (
<MyContext.Provider value="Hello World">
<GrandParent />
</MyContext.Provider>
);
}
이렇게 하면 원하는 컴포넌트에서 useContext
라는 Hook을 사용하여 Context에 넣은 값에 바로 접근할 수 있다.
해당 Hook의 인자에는 createContext
로 만든 Mycontext
를 넣는다.
import { createContext, useContext } from 'react';
function Message() {
const value = useContext(MyContext);
return <div>Received: {value}</div>;
}
Provider 하위에서 context를 구독하는 모든 컴포넌트는 Provider의 value prop가 바뀔 때마다 다시 렌더링 된다.
1.createContext() 함수를 사용하여 Context 만들기
2.최상위 컴포넌트에서 Provider로 감싸기
3.하위 컴포넌트에서 context API 설정하기
value
값을 따로 지정하지 않았기 때문에 undefined
로 조회된다.
기본값을 설정하고 싶다면 createContext
함수에 인자로 기본 값을 넣어주면 된다.
const MyContext = createContext('default value');
Provider를 새로 만들어 주는 것이 좋다.
import { createContext } from 'react';
const CounterContext = createContext();
function CounterProvider({ children }) {
return <CounterContext.Provider>{children}</CounterContext.Provider>;
}
function App() {
return (
<CounterProvider>
<div>
<Value />
<Buttons />
</div>
</CounterProvider>
);
}
// (...)
children
Props를 받아와서 CounterContext.Provider
태그 사이에 넣어주면 된다. 그 다음엔 필요한 기능들을 CounterProvider
컴포넌트 안에서 구현해주면 된다.
Context를 이렇게 따로따로 작성하지 않고 하나의 context.js 파일을 만들어서 관리할 수도 있다.
import * as React from 'react'
const CountContext = React.createContext()
function countReducer(state, action) {
switch (action.type) {
case 'increment': {
return {count: state.count + 1}
}
case 'decrement': {
return {count: state.count - 1}
}
default: {
throw new Error(`Unhandled action type: ${action.type}`)
}
}
}
// Custom Provider
function CountProvider({children}) {
const [state, dispatch] = React.useReducer(countReducer, {count: 0})
const value = {state, dispatch}
return <CountContext.Provider value={value}>{children}</CountContext.Provider>
}
// Custom Consumer
function useCount() {
const context = React.useContext(CountContext)
if (context === undefined) {
throw new Error('useCount must be used within a CountProvider')
}
return context
}
// 최상단 컴포넌트에서 Custom Provider를, 각 컴포넌트에서 이 Custom Consumer를 사용할 수 있다.
export {CountProvider, useCount}
컴포넌트에 context가 연결되면 재사용성이 떨어지므로 꼭 필요한 곳에만 사용하도록 한다.
Context API는 상태 관리 도구가 아니며 상태 관리 자체는 직접 관리해야한다. Context API는 그저 전역적으로 상태를 공유(상태가 아니더라도 데이터(값)이라면 무엇이든) 해주는 기능만 수행한다. Context API는 useState
,useReducer
를 통해 직접 상태관리를 하는 함수들을 props없이 전달해주는 것 뿐이다.
그에 반해 Redux는 상태를 관리해준다.
😮여기서 상태 관리란 ?
초기 값을 저장한다.
현재 값을 읽을 수 있다.
값 업데이트가 가능하다.