Context API

지은·2023년 3월 9일
0

⚛️ React

목록 보기
17/23
post-custom-banner

Context

일반적인 React 애플리케이션에서 데이터는 위에서 아래로 props를 통해 전달된다.
하지만 언어나 테마같이 여러 컴포넌트에 전해줘야하는 props가 있을 경우, 이 과정이 번거로울 수 있다. (props drilling 발생..)

이때 context를 이용하면, 트리 구조에서 단계마다 props를 넘겨주지 않아도 많은 컴포넌트가 값을 공유하도록 할 수 있다.
Context - React

언제 context를 써야할까?

context는 React 컴포넌트 트리 안에서 전역적(global)인 값을 공유할 수 있도록 고안된 방법이다.
e.g. 현재 로그인한 유저, 사용자가 선호하는 언어, 테마 등..

예를 들어, 아래의 코드는 버튼 컴포넌트를 꾸미기 위해 테마 props를 명시적으로 3단계나 넘겨주고 있다.

class App extends React.Component {
  render() {
    return <Toolbar theme='dark' /> // props 1차 전달
  }
}

function Toolbar(props) {
  return (
    <div>
      <ThemeButon theme={props.theme} /> // props 2차 전달
    </div>
  );
}

class ThemeButton extends React.Component {
  render() {
    return <Button theme={this.props.theme} /> // props 3차 전달
  }
}

위의 코드에서 context를 사용하면, props를 전달하지 않고 아래처럼 작성할 수 있다.

const ThemeContext = React.createContext('light'); // createContext() 메소드로 context를 생성할 수 있다.

class App extends React.Component {
  render() {
    return (
      <ThemeContext.Provider value='dark'> // Provider를 이용해 하위 트리의 모든 컴포넌트에 테마 값을 보내줄 수 있다.
        <Toolbar /> // props 전달 X
      </ThemeContext.Provider>
    );
  }
}

function Toolbar() {
  return (
    <div>
      <ThemeButon /> // props 전달 X
    </div>
  );  
}

class ThemeButton extends React.Component {
  static contextType = ThemeContext; // 가장 가까이 있는 Provider를 찾아 값를 읽어온다.
  render() {
    return <Button theme={this.context} /> // 'dark'
  }
}

Context API

React.createContext()

: Context 객체를 만드는 메소드

  • Context 객체를 구독하고 있는 컴포넌트가 렌더링될 때, React는 트리 상위에서 가장 가까이 있는 짝이 맞는 Provider로부터 현재값을 읽는다.
  • 이때 React가 트리 안에서 적절한 Provider를 찾지 못했을 경우 defaultValue가 쓰인다.
const ThemeContext = React.createContext('light');

<Context.Provider>

: context를 구독하는 컴포넌트들에게 context의 변화를 알리는 역할을 하는 React 컴포넌트

  • Provider는 value prop을 받아서 이 값을 하위 컴포넌트들에게 전달한다.
  • Provider 하위에 또 다른 Provider를 배치하는 것도 가능하며, 이 경우 하위 Provider의 값이 우선시된다.
  • Provider 하위에서 context를 구독하는 모든 컴포넌트들은 Provider의 value prop이 바뀔 때마다 다시 렌더링된다.
<ThemeContext.Provider value='dark'>
  <하위 컴포넌트>
</ThemeContext.Provider>

Class.contextType

: React.createContext()로 생성한 Context 객체를 원하는 클래스의 contextType 프로퍼티로 지정할 수 있다.

  • 이 프로퍼티를 활용해 클래스 안에서 this.context로 해당 Context의 값을 읽을 수 있다. (이때 가장 가까운 Provider를 찾아 값을 읽어온다.)
class ThemeButton extends React.Component {
  static contextType = ThemeContext; // ThemeButton 클래스의 contextType 프로퍼티로 ThemeContext 객체를 지정
  render() {
    let value = this.context;
    /* context 값을 이용한 렌더링 */
  }
}
  • 이렇게 읽어온 값은 render()를 포함한 모든 컴포넌트 생명주기 메소드에서 활용할 수 있다.
class ThemeButton extends React.Component {
  componentDidMount() {
    /* context 값을 이용한 코드 */
  }
  componentDidUpdate() {
    /* ... */
  }
  componentWillUnmount() {
    /* ... */
  }
    
  render() {
    let value = this.context;
  }
}
ThemeButton.contextType = ThemeContext; // ThemeButton 클래스의 contextType 프로퍼티로 ThemeContext 객체를 지정

<Context.Consumer>

: context 변화를 구독하는 React 컴포넌트
이 컴포넌트를 사용하면 함수 컴포넌트 안에서 context를 구독할 수 있다.

  • Context.Consumer의 자식은 함수여야 하며, 이 함수는 context의 현재값을 받고 React 노드를 반환한다.
<ThemeContext.Consumer>
  {value => <함수 컴포넌트 value={value} />}
</ThemeContext.Consumer>

Context.displayName

: Context 객체는 displayName이라는 문자열 속성을 설정할 수 있다.
React 개발자 도구는 이 문자열을 사용해서 context를 어떻게 보여줄지 결정한다.

const ThemeContext = React.createContext('light');
ThemeContext.displayName = 'ColorTheme';

<ThemeContext.Provider> // 'ColorTheme.Provider' in DevTools
<ThemeContext.Consumer> // 'ColorTheme.Consumer' in DevTools

context를 사용하기 전에 고려할 것

context의 주된 용도는 다양한 레벨에 네스팅된 많은 컴포넌트에게 데이터를 전달하는 것이다.

단순히 props drilling을 대체하기 위해 context를 사용해서는 안된다. context를 사용하면 컴포넌트를 재사용하기 어려워지기 때문이다. 따라서 꼭 필요할 때만 사용해야한다. props drilling을 해결하기 위해서는 컴포넌트 합성을 사용하는 것이 좋다.

profile
블로그 이전 -> https://janechun.tistory.com
post-custom-banner

6개의 댓글

comment-user-thumbnail
2023년 3월 10일

항상 깔끔한 정리네요 컨텍스트 api 개념 다시 정리하고 갑니다

답글 달기
comment-user-thumbnail
2023년 3월 12일

오호 재사용이 어렵군요

답글 달기
comment-user-thumbnail
2023년 3월 12일

잘 복습하고 갑니다 !!

답글 달기
comment-user-thumbnail
2023년 3월 12일

여기에 상태관리 라이브러리까지 쓰면 금상첨화겠군요 잘봤습니낟

답글 달기
comment-user-thumbnail
2023년 3월 12일

저도 이번에 컨텍스트를 썼는데 여기 개념이 있네요 궁금한부분 싹 긁고 갑니다 감사합니다!

답글 달기
comment-user-thumbnail
2023년 3월 12일

context 모르고 있던 부분까지 정리를 잘해주셔서 공부가 많이 되었습니다!

답글 달기