Context API

jaemin·2020년 12월 30일
0

리액트

목록 보기
11/16
post-thumbnail

Context

context를 이용하면 단계마다 일일이 props를 넘겨주지 않고도 컴포넌트 트리 전체에 데이터를 제공할 수 있다.

상위 컴포넌트에서 데이터를 Set하고 set한 데이터를 하위 컴포넌트에서 get할 수 있어야 한다. context를 사용하려면 데이터를 set하는 과정과 get하는 과정이 필요하다.

데이터 Set 하기

모든 하위 컴포넌트가 데이터를 가져올 수 있어야 하므로 데이터를 set하는 곳은 가장 상위 컴포넌트여야 한다.

데이터를 Set하는 순서는,

  1. 상위 컴포넌트에서 컨텍스트를 생성한다.
  2. 컨텍스트, 프로바이더를 사용한다.
  3. value를 사용한다.

1. 상위 컴포넌트에서 컨텍스트 생성

src 아래에 contexts라는 폴더를 생성하고 PersonContext.jsx 파일을 만든다.

// PersonContext.jsx
import React from 'react';

const PersonContext = React.createContext();

export default PersonContext;

2. 프로바이더와 value prop 사용

// index.js (가장 상위 컴포넌트)

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import PersonContext from './contexts/PersonContext';

const persons = [
  { id: 0, name: 'Mark', age: 38 },
  { id: 1, name: 'Hanna', age: 27 },
];

ReactDOM.render(
  <PersonContext.Provider value={persons}>
    <App />
  </PersonContext.Provider>,
  document.getElementById('root'),
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
reportWebVitals();

Context 객체에 포함된 React Component인 Provider는 context를 구독하는 컴포넌트들에게 context의 변화를 알리는 역할을 한다.

Provider 컴포넌트는 value prop을(여기서 persons) 받아서 이 값을 하위에 있는 컴포넌트에게 전달한다. Provider 하위에서 context를 구독하는 모든 컴포넌트는 Provider의 value prop이 바뀔 때마다 다시 렌더링된다.

여기까지 데이터를 Set 하는 과정이었다. 이제 어떻게 데이터를 Get하는지 알아보자.

데이터를 Get 하기

데이터는 모든 하위 컴포넌트에서 접근 가능하다. 접근 방법에는 세가지가 있다.

  1. Consumer로 Get 하는 방법
  2. 클래스 컴포넌트의 this.context로 하는 방법
  3. 함수형 컴포넌트의 useContext로 하는 방법

1. Consumer로 Get 하는 방법

src 아래에 component 폴더를 생성하고 Example1.jsx 파일을 만든다.

// Example1.jsx
import React from 'react';
import PersonContext from '../contexts/PersonContext';

const Example1 = () => (
  <PersonContext.Consumer>
    {value => <ul>{JSON.stringify(value)}</ul>}
  </PersonContext.Consumer>
);

export default Example1;

Context.Consumer의 자식은 함수여야 한다. 이 함수는 context의 현재 value(Provider가 주는 value)를 받고 React 노드를 반환한다. 이 함수가 받는 value 값은 해당 context의 Provider 중 상위 트리에서 가장 가까운 Provider의 value prop과 동일하다. 상위에 Provider가 없다면 value 값은 createContext()에 인자로 보냈던 defaultValue와 동일하다.

Example1이 잘 만들어졌나 렌더링해보자.

// App.js
import React from 'react';
import logo from './logo.svg';
import './App.css';
import Example1 from './components/Example1';

export default function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <Example1 />
      </header>
    </div>
  );
}

persons 데이터를 잘 받아온 것을 알 수 있다.

  1. context 가져온다.
  2. 컨텍스트, 컨슈머 사용한다. <PersonContext.Consumer>
  3. value 사용한다.

2. 클래스 컴포넌트의 this.context 방법

// ./components/Example2.jsx
import React from 'react';
import PersonContext from '../contexts/PersonContext';

export default class Example2 extends React.Component {
  static contextType = PersonContext;

  render() {
    return <ul>{JSON.stringify(this.context)}</ul>;
  }
}

// Example2.contextType = PersonContext;

contextType이라는 클래스 변수(정적 프로퍼티)를 생성하고 값은 PersonContext를 할당한다. 그러면 해당 클래서 안에서 this.context를 이용해 해당 Context의 가장 가까운 Provider를 찾아 그 값을 읽을 수 있게 된다.

this.context는 Provider로부터 받은 value 와 같다.(중요)

  1. static contextType에 컨텍스트를 설정
  2. this.context === value

3. 함수형 컴포넌트의 useContext 방법

// ./components/Example3.jsx
import React, { useContext } from 'react';
import PersonContext from '../contexts/PersonContext';

const Example3 = () => {
  const value = useContext(PersonContext);

  return <ul>{JSON.stringify(value)}</ul>;
};

export default Example3;
  1. useContext로 컨텍스트를 인자로 호출한다. useContext(PersonContext)
  2. useContext의 리턴이 value이다.

Context.displayName

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

예를 들어, 아래 컴포넌트는 개발자 도구에 MyDisplayName로 표시된다.

// PersonContext.jsx
import React from 'react';

const PersonContext = React.createContext();

PersonContext.displayName = 'MyDisplayName';

export default PersonContext;
profile
프론트엔드 개발자가 되기 위해 공부 중입니다.

0개의 댓글