본문 바로가기

공부기록/[강의노트] Udemy React 완벽가이드 101~200

# 130 [udemy React 완벽 가이드 노트] 리액트 컨텍스트 provider, consumer, useContext

1. 리액트 컨텍스트 작성 하기 

    1) 파일 추가하기

    2) react를 import한다. 

 

    3) React.createContext() 작성 

 

 

        React.createContext()는 컨텍스트 객체를 생성한다.

        기본 컨텍스트를 만드는 것이다.

        앱이나 빈 state의 컴포넌트. 

 

        object일 수도 있고 그저 문자열일 수도 있다. 작성자 마음. 

 

 

        createContext에서 얻는 결과는 컴포넌트나 컴포넌트를 포함하는 객체가 될 것이다. 

const AuthContext = React.createContext({
  isLoggedIn: false
});

 

 

AuthContext는 컴포넌트가 아니지만 

컴포넌트를 포함하는 객체이다. 

 

 4) AuthContext import하기

 

 

2. Provide 와 Consume

 

 1) Provide 

 

    리액트에 context가 있는 것을 알려주기 

    그것을 감싸는 모든 컴포넌트는 context에 접근 권한이 있다. 

    그래야 컨텍스트를 리스닝 할 수 있다. 

 

 

●   context를 활용하여야 하는 컴포넌트를 감싸기 

 

 

모든것이 다 context에 접근 권한이 있으려면 App 컴포넌트를 감싸자. 


  return (
    <AuthContext.Provider>
      <MainHeader isAuthenticated={isLoggedIn} onLogout={logoutHandler} />
      <main>
        {!isLoggedIn && <Login onLogin={loginHandler} />}
        {isLoggedIn && <Home onLogout={logoutHandler} />}
      </main>
    </AuthContext.Provider>
  );

그러면 모든 자식의 자식의 자식 컴포넌트까지도 모두 context 에 접근할 수 있게 되었다. 

 

 

2) Consume

  연동하고 리스닝하기 

 

 

        (1) AuthContext consumer를 사용하기 

 

사용자 인증여부가 필요하다면 

AuthContext를 사용할 수 있다. 

그리고 데이터가 필요한 모든 것을 Consumer로 감싸주자.

 

 

Consumer는 자식을 가지는데  자식은 중괄호 안의 함수다.

인수로 컨텍스트 데이터를 가져온다.

 

그리고 해당 데이터에 접근할 수 있는 navigation의 jsx코드를 모두 return해준다. 

 

 

import React from "react";
import AuthContext from "../context/auth-context";

import classes from "./Navigation.module.css";

const Navigation = props => {
  return (
    <AuthContext.Consumer>
      {ctx => {
        return (
          <nav className={classes.nav}>
            <ul>
              {ctx.isLoggedIn && (
                <li>
                  <a href="/">Users</a>
                </li>
              )}
              {ctx.isLoggedIn && (
                <li>
                  <a href="/">Admin</a>
                </li>
              )}
              {ctx.isLoggedIn && (
                <li>
                  <button onClick={props.onLogout}>Logout</button>
                </li>
              )}
            </ul>
          </nav>
        );
      }}
    </AuthContext.Consumer>
  );
};

export default Navigation;

 

 

그런데 기본값은   Provider 없이 Consume할 때만 쓰는 것이다. 

 

createContext({
  isLoggedIn: false,
});

 

그래서 오류가 난다. 

 

 

 

우리 목표는 변할 수 있는 context값을 가지는 것

이때는 Provider가 필요하다

수정해야 할 것

 

 

 

●  default 객체를 가져오자. 

 

    <AuthContext.Provider value={{}}>

반드시 value라는 속성을 가지고 있어야 한다.

여기에 context의 default 객체를 가지고 올 수 있다.

 

그러면 오류는 사라지고 작동 한다. 

 

그런데 원래 있던 MainHeader의 오른쪽에 있던 Users와 Admin 링크 버튼이 사라졌다.

isLoggedIn상태가 변하지 않기 때문이다. 

 

●  context 객체의 isLoggedIn 상태를 변경해보자. 

 

App 컴포넌트에서 관리하고 있는 state이다. 

 

 

  const [isLoggedIn, setIsLoggedIn] = useState(false);

 

 

 

이 state를 AuthContext.Provider의 value의 값으로 넣어준다. 그러면 state가 때에 따라 변경된다. 

 

 

 

    <AuthContext.Provider
      value={{
        isLoggedIn: isLoggedIn,
      }}
    >

 

value 객체는 isLoggeIn이 변경될 때마다 업데이트 될 것이고 

새로운 컨텍스트 객체는 모든 Consume리스닝 컴포넌트로 전달된다. 

prop을 쓸 필요가 없게 된다. 

 

 

 

      <MainHeader isAuthenticated={isLoggedIn} onLogout={logoutHandler} />

여기에 isAuthenticated prop은 이제 삭제해도 된다. Provider를 통해 isLoggeIn이 전달되었기 때문이다. 

 

 

 

MainHeader 컴포넌트에서도 그렇다.

<Navigation isLoggedIn={props.isAuthenticated} onLogout={props.onLogout} />

 

 

 

이제 Navigation.js에서 모든 isLoggedIn 상태 정보를 사용할 수 있게 되었다.

 

import React from "react";
import AuthContext from "../context/auth-context";

import classes from "./Navigation.module.css";

const Navigation = props => {
  return (
    <AuthContext.Consumer>
      {ctx => {
        return (
          <nav className={classes.nav}>
            <ul>
              {ctx.isLoggedIn && (
                <li>
                  <a href="/">Users</a>
                </li>
              )}
              {ctx.isLoggedIn && (
                <li>
                  <a href="/">Admin</a>
                </li>
              )}
              {ctx.isLoggedIn && (
                <li>
                  <button onClick={props.onLogout}>Logout</button>
                </li>
              )}
            </ul>
          </nav>
        );
      }}
    </AuthContext.Consumer>
  );
};

export default Navigation;

 

 

        (2) 리액트 컨텍스트 훅을 사용하기

 

 

다른 방법도있다. 리액트의 컨텍스트 훅을 사용하는 방법이다.

 

1) useContext를 import하기 

useContext는 컨텍스트를 활용하고 리스닝할 수 있게 해줌 

2) 리액트 컴포넌트 함수에서 useContext를 호출해 준다. 

컨텍스트에게 사용하려는 컨텍스트 포인터를 전달한다. 

 

import React, { useContext } from "react";
import AuthContext from "../context/auth-context";

import classes from "./Navigation.module.css";

const Navigation = props => {
  const ctx = useContext(AuthContext);
  return (
    <nav className={classes.nav}>
      <ul>
        {ctx.isLoggedIn && (
          <li>
            <a href="/">Users</a>
          </li>
        )}
        {ctx.isLoggedIn && (
          <li>
            <a href="/">Admin</a>
          </li>
        )}
        {ctx.isLoggedIn && (
          <li>
            <button onClick={props.onLogout}>Logout</button>
          </li>
        )}
      </ul>
    </nav>
  );
};

export default Navigation;