OLD/React

[React] React Context (useContext)

joseph0926 2023. 3. 3. 09:24

이번에 정리할 내용은 Context다.

내가 이걸 처음 배웠을 떄 마법이라 느꼈다.

조금 과장하는면도 있지만, 여태까지의 힘들었던것들을 뚫어주는 면에서는 마법 그 자체였다.

 

또한, 이게 있는데 왜 힘들게 props 드릴링을 사용하지? 라는 의문도 들었다.

(이건 마지막에 서술할 context 한계에서 알아보자)

 

내가 왜 이런 느낌이 들었는지 정리해보겠다.

 

이 글에서 알아볼 것

  • Context

 

1. Context

  • 여태까지 우리는 리액트에서 데이터 전달을 props을 이용해 수행해왔다.
    • 하지만 이 방식은 큰 한계점이 존재했었는데, 바로 직속으로만 전달할수있다는 점이였다. (상위 or 하위 상관없이)
    • 이러면 A라는 state를 여러 곳에서 사용하고 싶거나, 직속이 아닌곳에서 사용할때 매우 많은 props 전달을 해야할것이다. (props 체인)
      • 즉, 앱이 작다면 문제될것이 없지만, 앱이 커지면 커질수록 이를 관리하기가 너무 힘들어진다…
    • 이를 리액트 내부에 존재하는 저장소인 Context라는 개념으로 해결할수있다
  • Context 사용법
    1. React.createContext();
      • createContext는 빈 context를 생성해준다.
        • 빈 context는 단순히 빈 state의 컴포넌트이다.
      • 여기에 인자로 특정 state를 넣어줄수있다..보통 객체로 넣어준다
    2. state를 받은 React.createContext는 컴포넌트를 포함할 객체를 반환한다
      • const AuthContext = React.createContext({~~~})
        • 즉, AuthContext 는 컴포넌트를 포함할 객체이다.
        • 이 AuthContext는 context 파일에서 필요한것이 아닌, 다른 곳에서 필요하다…따라서 내보낸다
          • export default AuthContext
    3. 앱에서 context를 사용하려면 두가지 작업이 필요하다
      1. 공급해줘야한다
        • 리액트에게 context의 존재를 알리는것
        • 보통 context의 state들은 앱 전체에 필요하므로, 최상위 루트 파일인 index.js에서 최상위 컴포넌트인 <App> 컴포넌트를 감싸주면된다
      2. 소비해야한다
        • 연동, 리스닝등을 해줘야한다
        • 이때 사용하는 것이 useContext 훅이다.
          1. const authCtx = useContext(AuthContext);
          2. authCtx.isLoggedIn(context에 정의한 state)
  • 위의 내용을 코드를 다시 보자
//auth-context.js
const AuthContext = React.createContext({
  isLoggedIn: false,
  onLogout: () => {},
  onLogin: () => {},
});

export const AuthContextProvider = (props) => {
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const logoutHandler = () => {
    setIsLoggedIn(false);
  };
  const loginHandler = () => {
    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/auth-context";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <AuthContextProvider>
    <App></App>
  </AuthContextProvider>
);
  • context 제한
    • 컴포넌트 구성을 대체할 수 없다
      • 예를들어 재사용가능한 Button 컴포넌트에 onClick={authCtx.onLogout}을 해버리면, 이 버튼은 보통 재사용할수없다…
        • 재사용할수는있지만, 무조건 버튼클릭시 로그아웃되는 버튼일것이다.
      • 즉, 이런 재사용 컴포넌트에는 props를 사용하는것이 좋다
    • 변경이 잦은 경우에는 적합하지않다
      • state의 변경이 잦은 상황에 context가 최적화되어있지않다
      • 이런 경우 Redux 사용하자 (다음 글에서 작성할 내용)

 

Context는 리액트를 이용해 큰 웹 애플리케이션을 구축할 때, 필수적으로 사용되어지는 기능이다.

따라서, 이를 완벽하게 이해하고있어야 한다.

 

단, 위에서 말한 단점 "변경이 잦은 경우에는 적합하지않다" 이 존재하는 경우에는 생각을 해봐야하는데,

이 문제를 완벽하게 해결해주는 기능이 리액트에는 또 존재한다.. 바로 Redux다.

 

다음 글에서는 Redux에 대해서 알아보고, Context와 Redux의 차이점도 알아보자