user들의 로그인 데이터와 상태들을 편리하게 관리하기 위해서 전역으로 관리할 필요성이 생겼다. 전역으로 state들을 관리할 수 있는 Context를 사용하기로 했다. redux와 역할이 흡사하다.
Context를 사용하여 state들을 사용하기 위해서는 createContext()
, Context 객체
, Provider component
, useContext() hook
을 모두 구성하고 사용해야 한다.
Context를 사용하기 위해서 createContext()
로 Context 객체를 생성하고 이 때 관리할 state
들을 종류들을 타입을 정의해준다. 초기값을 설정해줄 필요는 없다.
// ContextProvider.js
import { createContext } from "react";
const Context = createContext({
loggedUser: {
username: '',
email: '',
first_name: '',
},
loggedIn: false,
setLoggedUser: () => {},
setLoggedIn: () => {}
});
export default Context;
Provider component
는 Context 객체의 하위 요소로 실질적으로 state
들을 저장하고 관리하는 공간이다. 이러한 공간을 보통 store
라고 한다.
Provider는 가장 상위의 component인 App component
의 자식들을 감쌀 것이기 때문에 children props
를 넘겨받는다.
// App.js
function App() {
return (
<ContextProvider>
<div className="App">
<Routes />
</div>
</ContextProvider>
);
}
Provider는 완전히 component를 정의한다고 생각하고 접근해야 한다. useState()
hook을 사용하여 사용할 state(Context에서 정의한 형태와 동일하게)을 정의하고 state 내부에는 state의 특정 요소들을 변경할 수 있는 함수까지 정의한다.
아래에서 setLoggedUser()
함수는 state의 loggedUser
부분만 변경할 수 있는 함수이며, setLoggedIn()
함수는 state의 loggedIn
부분만 변경할 수 있는 함수이다.
마지막으로 미리 정의한 Context 객체를 가져와서 Context.Provider
component를 JSX
로 정의하고 value
props 로 위에서 정의한 state을 넘겨준다.
// ContextProvider.js
const ContextProvider = ({children}) => {
const setLoggedUser = (data) => {
setState(prevState => (
{
...prevState,
loggedUser: data
}
))
}
const setLoggedIn = () => {
setState(prevState => (
{
...prevState,
loggedIn: !prevState.loggedIn
}
))
}
const initialState = {
loggedUser: {},
loggedIn: false,
setLoggedUser,
setLoggedIn
}
const [state, setState] = useState(initialState);
return (
<Context.Provider value={state}>
{children}
</Context.Provider>
)
}
이렇게 ContextProvider를 App
component에서 연결하면 App 하위에 존재하는 모든 component들에서 login과 관련한 state을 사용할 수 있다. 특정 하위 component에서 사용하기 위해서는 useContext
hook을 사용하여 Provider
에서 정의한 state들을 가져올 수 있다.
const { loggedUser, loggedIn, setLoggedUser, setLoggedIn } = useContext(Context);
단순히 값을 가져올 수도 있지만, setter
함수들도 가져와서 state의 값들을 변경하는데 사용할 수 있다.