React

UseContext(Context API)

selonjulie 2022. 7. 7. 11:48

해결하려는 문제

  • 일반적으로 데이터는 props를 통해 컴포넌트에 전달됨
  • 하지만 props를 통해서 '여러 컴포넌트를 거쳐' 많은 데이터를 전달할 경우에, 그 데이터를 사용하지 않는 컴포넌트에도 그 데이터를 전달하기 위해 props이 쓰임. 앱이 큰 경우에 전달하는 체인이 점점 더 길어질 수 있음
    • (eg) login함수. login state는 앱 곳곳에서 필요함

해결책

  • props를 실제로 필요한 데이터를 부모로부터 받는 컴포넌트에서'만' 사용하기
  • 앱 안에서 전역적으로 사용되는 데이터들을 여러 컴포넌트들끼리 쉽게 공유할 수 있는 방법
  • 리액트에 내장된 내부적인 state저장소가 있음 => reactContext(Context API)
  • reactContext를 사용하면 그 컴포넌트 전체 state저장소에서 액션을 트리거할 수 있음. 그 후 관련된 컴포넌트에 직접 전달 하 수 있음. 이렇게 하면 props로 데이터를 일일히 전달해(Data drilling) 주지 않아도됨

사용법

  • 보통 store, context라는 폴더명으로 관리
  • 파일은 컴포넌트가 포함되지 않는다면 파스칼 표기법(AuthContext.js) 대신 케밥 표기법(auth-context.js)으로 표시
  • React.createContext()로 context 객체를 만듦
  • () 내부에는 객체인 경우가 많음

참고)

React | React.createContext

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

1. 공급하기

-리액트에 '여기 내 컨텍스트가 있다'라고 알려줘야함. 그것이 감싸는 모든 컴포넌트는 접근 권한이 있어야함

-그 컨텍스트를 활용할 수 있어야하는 모든 컴포넌트를 JSX코드로 감싼다. 그러면 해당 컨텍스트를 들을 수 있음. 감싸지지 않은 컴포넌트는 리스닝 할 수 없다

-감싼 컴포넌트의 모든 자식 컴포넌트들은 해당 컴포넌트에 접근 할 수 있음

-AuthContext.Provider

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

2. 소비하기

-React.create() 내부의 값에 접근하기 (리스닝 부분) 2가지 방법

1) AuthContext.Consumer

2) useContext 훅 (일반적인 방법)

 

1) AuthContext.Consumer

-사용자가 인증되어있는지 여부를 알고 싶다면, JSX로 해당 return문을 AuthContext.Consumer로 감싸기

-소비자는 함수인 자식을 가지고 있음. 매개변수로는 context 데이터를 가짐

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) useContext 훅 (일반적인 방법): Context를 사용하고 리스닝하게 해줌

import React, { useContext } from "react";

import classes from "./Navigation.module.css";
import AuthContext from "../../store/auth-context";

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;

 

하지만

-Context를 사용하면 컴포넌트를 재사용하기 어려워 질 수 있음

:해당 context의 store를 구독하게됨, 데이터 하나를 결합하여 사용. 다른 컴포넌트와 결합이 되버리면 계속 그 컴포넌트와 연결되니까  (재사용 하려면 props를 사용)

-Prop drilling을 피하기 위한 목적이라면 컴포넌트 합성Component compoisition을 고려해봄

*컴포넌트 합성: props.children 사용. 컴포넌트를 계속 불러오면서 합성할 수 있음.

 

Context + useReducer 조합이면 Redux와 동일하게 사용할 수 있다

->Flux 패턴

 

사용하는 곳

로그인시 token, 테마

 

Context를 공유하는 지점은 Provider이다

공유받은 context를 사용할때는 useContext사용

 

Consuming context

필요한 context가 바꼈을때만 랜더링 하자. 어떤 context를 바라볼지 정하기

Provider에서 Value를 넘기는 부분을 state처럼 사용할 수 있게 하기위해 

*배열도 넣을 수는 있다

-이름을 바꿔야하면 배열로 넘기기

-명시적으로 써야한다 하면 객체로 넘기기

 

Flux패턴

Dispatch로 바뀜. 이것을 통해서만 상태를 바꿀 수 있다 (useState말고)

dispatch안에 action 함수가 있음-상태변화를 예측하기 쉽게 만들기 위해

Dispatch - action함수 - reducer 로 상태 변하게 함

 

Redux는 context API에서 flux패턴이 합쳐진 형태이다

 

 

출처

React Hooks에 취한다 - useContext + Context API | 리액트 훅스 시리즈

 

'React' 카테고리의 다른 글

버튼 클릭 시에만 input값 변경하기  (0) 2022.08.18
axios put 사용, header 사용법  (0) 2022.08.17
데이터 get하기/데이터에 따라 버튼 색 바꾸기  (0) 2022.08.16
Mock Data 활용법  (0) 2022.06.25
여러개의 input관리  (0) 2022.05.30