Tech/ReactJS

[React] 컨텍스트 API 활용

닝닝깅 2021. 7. 16. 14:35

컨텍스트 API를 활용하면 기존 공급자와 소비자를 컴포넌트로 구현하여 컨텍스트를 구성하는 과정을 대체할 수 있다.

 

createContext() 함수 : 공급자와 소비자를 반환하는 컨텍스트를 생성하는 함수

const MyContext = React.createContext(defaultValue);

공급자는 MyContext.Provider , 소비자는 MyContext.Consumer로 접근해서 사용하거나

const{ Provider, Consumer } = React.createContext(defaultValue);와 같이 분할 할당하여 사용한다.

 

컨텍스트 API 사용해보기

(로딩상태를 표시하는 공급자 컴포넌트 예시)

 

1. createContext()함수로 공급자 만들기

import React from 'react';
//빈 객체를 인자로 전달하여 소비자와 공급자 생성
const { Provider, Consumer } = React.createContext({});

//소비자를 export, 이후 소비자가 공급자의 컨텍스트 데이터를 구독하게 될 것
export { Consumer };

export default class LoadingProvider extends React.Component {
  constructor(props) {
    super(props);

    this.state = {};
    this.setLoading = this.setLoading.bind(this);
  }

  setLoading(key, value) {
    const newState = { [key]: value };
    this.setState(newState);
  }

  render() {
    const context = {
      ...this.state, //컨텍스트데이터에 state값과 setLoading()추가
      setLoading: this.setLoading,
    };

    return <Provider value={context}> //공급자가 공유할 컨텍스트 데이터 value프로퍼티에 전달
    {this.props.children} //자식 프로퍼티를 출력하여 자식 컴포넌트에 컨텍스트 데이터 전달
    </Provider>; 
  }
}

 

2. 한 개의 공급자를 구독하는 세 개의 소비자 만들기

컨텍스트 API의 Consumer컴포넌트

// 프로퍼티의 이름으로 children 사용
function Consumer({children}, context){ 
    return children(context);
};

 

import React from 'react';
import PropTypes from 'prop-types';
import Button from '../04/Button';
import { Consumer } from './LoadingProviderWithNewContext';

function ButtonWithNewConsumer({ label }) {
  return (
    <React.Fragment>
    
    //첫번째 소비자
    //공급자의 value프로퍼티에 전달된 값을 인자로 받아 Button컴포넌트 출력
      <Consumer>
        {value => (
          <Button onPress={() => value.setLoading('loading', !value.loading)}>
            {value.loading ? '로딩중' : label}
          </Button>
        )}
      </Consumer>
      
      //두번째 소비자
      //객체 분할 할당식으로 컨텍스트 데이터 loading2, setLoading을 인자로 받아 Button컴포넌트 출력
      <Consumer>
        {({ loading2, setLoading }) => (
          <Button onPress={() => setLoading('loading2', !loading2)}>
            {loading2 ? '로딩중' : label}
          </Button>
        )}
      </Consumer>
     
      //세번째 소비자
      //컨텍스트 데이터 loading, loading2을 동시에 구독한 다음 Button 컴포넌트에 메세지 출력
      <Consumer>
        {({ loading, loading2 }) => (
        <Button>
          {loading && loading2 ? '로딩중' : label}
        </Button>})
      </Consumer>
    </React.Fragment>
  ); 
}

ButtonWithNewConsumer.propTypes = {
  label: PropTypes.string,
};

export default ButtonWithNewConsumer;