context API란?
props drilling을 사용하기 싫을 때, 즉 컴포넌트에 상관없이 전역적으로 데이터를 이용하고 싶을 때 사용한다. context API 사용 시 전역 데이터를 Context에 저장한 후, 데이터가 필요한 컴포넌트에서 해당 데이터를 불러와 사용할 수 있다. 로그인 데이터, 웹 내 사용자가 쓰는 설정파일, 테마, 언어 등등 다양하게 컴포넌트 간 공유되어야 할 데이터로 사용하면 좋다.
context API를 사용하고 싶을 때에는 context, provider, consumer 이 세 가지 개념만 숙지하면 된다.
1. Context(전역 값 저장)
Context 를 만들 땐 다음과 같이 React.createContext() 라는 함수를 사용한다.
// context.js
import React, { useState } from 'react';
const AuthContext = React.createContext({
isLoggedIn: false,
onLogout: () => {},
onLogin: (email, password) => {},
});
변수에 React.createContext 함수를 담고 인자로 기본값을 준다. 기본값은 트리 안에서 적절한 Provider를 찾지 못했을 때만 쓰이는 값이다. 이렇게 Context를 만들면 AuthContext.Provider라는 컴포넌트와 AuthContext.Consumer라는 컴포넌트가 만들어진다.
2. Provider(전역 값 제공)
Provider는 Context 안에 있는 값을 사용할 컴포넌트들을 감싸주는 용도로 사용한다. 값을 정할 때는 value에 값을 설정해 준다. 이 값이 바로 Context를 통해 여러 컴포넌트에서 공유할 수 있는 값이다.
App 컴포넌트에서 useState를 사용해 관리하는 상태를 Provider로 넣어주면(isLoggedIn) 값이 바뀔 때 useContext를 사용하는 컴포넌트 쪽에서도 리렌더링이 잘 발생할 것이다. Provider를 사용하는 컴포넌트에서 Context의 상태를 관리하는 것보다는 아래 처럼(context.js) Provider 전용 컴포넌트를 따로 만드는 것이 유지보수성이 더 높다. 특히 Context에서 다루는 로직이 복잡할 때는 전용 컴포넌트를 만드는 것이 좋다.
//context.js
export const AuthContextProvider = props => {
const [isLoggedIn, setIsLoggedIn] = useState(false);
useEffect(() => {
const storedUserLoggedInInformation = localStorage.getItem('isLoggedIn');
if (storedUserLoggedInInformation === '1') {
setIsLoggedIn(true);
}
}, []);
const logoutHandler = () => {
localStorage.removeItem('isLoggedIn');
setIsLoggedIn(false);
};
const loginHandler = () => {
localStorage.setItem('isLoggedIn', '1');
setIsLoggedIn(true);
};
return (
<AuthContext.Provider
value={{
isLoggedIn: isLoggedIn,
onLogout: logoutHandler,
onLogin: loginHandler,
}}>
{props.children}
</AuthContext.Provider>
);
};
export default AuthContext;
// index.js
import { AuthContextProvider } from './context.js';
ReactDOM.render(
<AuthContextProvider>
<App /> // Provider 사이에 있는 컴포넌트는 전역 상태에 접근할 수 있다.
</AuthContextProvider>,
document.getElementById('root')
);
3. Consumer(전역 값 조회)
useContext 훅을 통 위에서 만든 context를 조회한다.
// 최종전달 컴포넌트
import React, { useContext } from 'react';
import AuthContext from './context.js';
const Home = props => {
const anthCtx = useContext(AuthContext);
return (
<Button onClick={anthCtx.onLogout}>Logout</Button>
);
};
장점으로는 prop drilling을 피할 수 있다는 것이 있다.
하지만 단점으로 잦은 업데이트를 위해서는 최적화되어있지 않다는 점이다. Provider 하위에서 context를 구독하는 모든 컴포넌트는 Provider의 value prop이 바뀔 때마다 다시 렌더링 된다. 그러므로 상태관리 라이브러리와 Context API를 상황에 맞게 비교하여 사용해야 한다.
예전에 상태관리 라이브러리의 종류가 많지 않을 땐 자주 쓰였지만 요즘은 리코일이 보편화되어 있기 때문에 리코일이 더 많이 쓰이는 것 같다. Context API에 대해 구글링 해봐도 최신 정보가 많지는 않은 것 같다(기분 탓 일 수도 있다).
참고한 블로그)
https://kyounghwan01.github.io/blog/React/react-context-api/
'온라인 강의(유데미, 인프런 등) > React 완벽 가이드(유데미)' 카테고리의 다른 글
[react & typescript] CRA로 typescript 설정하기(feat. esLint, styled-component) (0) | 2023.02.23 |
---|---|
[react] forwardRef (1) | 2023.02.22 |
[react] useReducer(feat. useState와 비교) (0) | 2023.02.21 |
[react] useEffect에서 Clean-up 함수 사용하기 (0) | 2023.02.21 |
[react] 제어 컴포넌트 vs 비제어 컴포넌트 (0) | 2023.02.20 |