context api란?

심서현·2022년 1월 18일
0

context api


일반적으로 부모와 자식간 props를 날려 state를 변화시켰던 react 방식과는 달리
context api는 컴포넌트 간 간격이 없다.
즉, 컴포넌트를 건너띄고 다른 컴포넌트에서 state, function을 사용할 수 있다.






✅ 언제 사용하는가


context는 컴포넌트 안에서 전역적으로 데이터를 공유하도록 나온 개념이다.
그런 데이터는 로그인 데이터, 웹 내 사용자가 쓰는 설정파일, 테마, 언어 등등 다양하게 컴포넌트 간 공유되어야할 데이터로 사용하는 것이 좋다.





React.createContext

const MyStore = React.createContext(defaultValue);
  • context 객체를 만든다.
    컴포넌트가 해당 context를 가지기 위해 해당 컴포넌트 상위 provider로 부터 context를 정의한 변수 myStore를 감싸면 된다.
  • defaultValue는 트리안에 적절한 provider를 찾지 못했을 때 쓰이는 값이다.
    (해당 store가 어떠한 provider에 할당되지 않은 경우)
    완전 독립적인 context를 유지할때 쓴다.




Context.Provider

<MyStore.Provider value={this.state}>
  <subComponent1 />
  <subComponent2 />
</MyStore.Provider>
  • provider는 정의한 context를 하위 컴포넌트에게 전달하는 역할
  • provider를 전달하는 변수는 꼭 value를 사용해야 한다.
  • 전달 받는 컴포넌트의 제한 수는 없다.
  • provider에 하위 provider배치가 가능하며, 그 경우 하위 provider값이 우선
  • provider 하위에 context를 가진 component는 provider의 value로 가진 state가 변화할 때마다, 전부 리렌더된다.




Context.Consumer

<MyContext.Consumer>
  {value => /* context 값을 이용한 렌더링 */}
</MyContext.Consumer>
  • context 변화를 구독하는 컴포넌트
  • context의 자식은 함수(컴포넌트)이어야 한다.
  • 이 함수(컴포넌트)가 가지는 context 값은 가장 가까운 provider값이다.
  • 상위 provider가 없다면 createContext()에서 정의한 defaultValue를 가진다.






📁 예시


createContext

// src/store.js
import React from "react";

const Store = React.createContext(null);
export default Store;
// src/rootStore.js
import React from "react";

const rootStore = React.createContext({ zxc: "testsetst" });
export default rootStore;



provider

// src/App.jsx

import React, { Component } from "react";
import Test from "components/Test";
import Test3 from "components/Test3";
import Test2 from "components/Test2";
import Store from "store";

export default class App extends Component {
  constructor(props) {
    super(props);
    this.changeMessage = () => {
      const { message } = this.state;
      if (message === "hello") {
        this.setState({
          message: "by"
        });
      } else {
        this.setState({
          message: "hello"
        });
      }
    };
    this.state = {
      test: "testContext",
      message: "hello",
      changeContext: this.changeMessage
    };
  }

  render() {
    const { test } = this.state;
    return (
      <Store.Provider value={this.state}>
        <Test test={test} />
        <Test2 />
        <Test3 />
      </Store.Provider>
    );
  }
}



consumer

// src/components/Test.jsx

import React, { Component } from "react";
import PropTypes from "prop-types";
import Store from "store";

export default class Test extends Component {
  render() {
    const { test } = this.props;
    return (
      <div>
        <Store.Consumer>{store => store.message}</Store.Consumer>
        <Store.Consumer>
          {store => (
            <button type="button" onClick={store.changeContext}>
              changeContext
            </button>
          )}
        </Store.Consumer>
        {test}
      </div>
    );
  }
}

Test.propTypes = {
  test: PropTypes.string
};

Test.defaultProps = {
  test: ""
};



2개의 store

// src/components/Test2.jsx
import React, { Component } from "react";
import rootStore from "rootStore";
import Store from "store";

export default class Test2 extends Component {
  static contextType = rootStore;

  componentDidMount() {
    // rootStore context 구독
    console.log(this.context);
  }

  render() {
    return (
      <>
        {/* store context 구독 */}
        <Store.Consumer>{store => store.message}</Store.Consumer>
        <div>test2 </div>
      </>
    );
  }
}



provider가 네스팅되어 상위 provider 값도 받아야 할때

// src/components/Test3.jsx
import React, { Component } from 'react';
import Store from 'store';
import rootStore from 'rootStore';
// import PropTypes from 'prop-types';

class TT extends Component {
  static contextType = rootStore;

  componentDidMount() {
    const { value } = this.props;
    console.log('ttt', value);
    console.log('root', this.context);
  }

  render() {
    const { value } = this.props;
    return <div>test3{value.message}</div>;
  }
}

const Test3 = () => <Store.Consumer>{store => <TT value={store} />}</Store.Consumer>;

export default Test3;

TT.propTypes = {
  value: {},
};

TT.defaultProps = {
  value: {},
};
profile
안녕하세요?

0개의 댓글