FE/REACT

[React] Context란 무엇이고 어떻게 사용할까? (Context API 그리고 관련 Hook)

mandelina 2022. 6. 15. 16:31

 

 

 

기존은 컴포넌트의 props를 통한 데이터 전달이 이루어 진다. 

 

하지만 여러 컴포넌트에 거쳐 자주 사용되는 데이터( 예 : 로그인여부, 프로필정보)의 경우 기존방식은 코드가

 

복잡하고 불편해진다.  이것을 해결하기위한 방법이 바로 Context이다. Context에 대해 알아보자!

 

 


 

 

Context ?

 

- 컴포넌트 트리를 통해 부모가 자식을 통해 전달해주는것이 아닌 곧바로 컴포넌트로 데이터 전달한다.

 

- 코드가 깔끔해지고, 데이터를 한곳에서 관리하기 때문에 디버깅도 유리하다. 

 

 

 

 

언제 context를 사용할까 ??

 

- 여러개의 component들이 접근해야하는 데이터에 사용

 

ex ) 로그인여부 , 정보 ui테마 , 현재언어 등 ..

 

 

 

 

사용하기전에 고려할점  

 

- component와 context가 연동되면 재사용성이 떨어진다.

 

- 따라서 다른레벨의 많은 컴포넌트가 데이터를 필요로 하는게 아니라면  props를 통한 데이터전달이 낫다.

 

- 전역으로 여기저기 사용되는 상태가 있고, 컴포넌트 개수가 많다면 Context를 사용하자! 

 

 

 

 

context API

 

1. context 생성

 

const Context = React.createContext(기본값);

 

- 상위레벨에 매칭되는 Provider가 없다면 기본값이 사용된다.

 

  (Provider없이 컴포넌트 테스트시 유리)

 

 

2. Context.Provider (제공자)

 

<Context.Provider value = { ... }>

 

- valuePrivider 컴포넌트의 하위 컴포넌트에 전달된다.

 

- value값은 무조건 상태값이 있어야 하는것은 아니고, 함수도 전달할 수 있다. 

 

- value값이 없으면 오류가 발생함을 주의하자.

 

- 참고로, 하나의 provider컴포넌트 여러개의 provider컴포넌트와 연결될 수 있다.

 

 

 

3.  Context.Consumer  (소비자)

 

<Context.Consumer>
	{value => /* 컨텍스트의 값에 따라 컴포넌트 렌더링 */}
</Context.Consumer>

 

- Provider에 의해 제공된 value를  하위컴포넌트들이 사용한다 .

 

- 이데이터를 소비한다 해서 Consumer이라고 한다.

 

- consumer 컴포넌트 Context의 값 변화를 지켜보다가 값이 변경되면 재 렌더링된다.

 

 

 

[ context API 예제]

 

import React, { createContext } from "react"; // 1번

const UserInfo = createContext({ name: "gary", id: "garyIsFree" }); //2번

const App = () => {
  return (
    <UserInfo.Provider value={{ name: "Licat", id: "ImLion" }}> // 3번
      <HelloLicat />
    </UserInfo.Provider>
  );
};

const HelloLicat = () => {
  return (
    <UserInfo.Consumer> //4번
      {(value) => (
        <div>
          <h2>{value.name}</h2>
          <strong>{value.id}</strong>
          <HelloLicatTwo/>
        </div>
      )}
    </UserInfo.Consumer>
  );
};

const HelloLicatTwo = () => {
  return (
    <UserInfo.Consumer> //4번
      {(value) => (
        <div>
          <h2>{value.name}</h2>
          <strong>{value.id}</strong>
        </div>
      )}
    </UserInfo.Consumer>
  );
};

export default App;

 

1.  createContext 를 import해준다.

 

2.  createContext로 UserInfo를 생성한다. 

 

3. Provider로 value 값을 하위 컴포넌트에게 전달해준다. (여기서 value는 { name: "Licat", id: "ImLion" } )

 

4. Consumer가 Provider로부터 값을 받아 사용한다. 즉,value.name = "Licat" 이 될 것이고, value.id = "ImLion" 이 될 것이다. 

 

 

 


 

Context에 있는 값을 Consumer 대신 다른 방법 없을까 ?

 

- useContext Hook을 사용하면 된다! 

 

- 함수형 컴포넌트에서 Context를 편하게 사용할 수 있다. 

 

 

useContext Hook 사용법

 

- 위 방식과 동일하게 createContext로 context를 생성해준다.

 

- 아래와 같이 useContext를 사용한다. 

 const { name, id } = useContext(UserInfo);

 

 

 

[예제]

 

import { useContext, createContext } from "react";

const UserInfo = createContext({ name: "gary", id: "garyIsFree" });

const App = () => {
  return (
    <HelloLicat/>
  );
};

//------- Consumer을 이용한 방식-----------------------------
// const HelloLicat = () => {
//   return (
//     <UserInfo.Consumer>
//       {(value) => (
//         <div>
//           <input type="text" />
//           <h2>{value.name}</h2>
//           <strong>{`@ ${value.id}`}</strong>
//         </div>
//       )}
//     </UserInfo.Consumer>
//   );
// };
//--------------------------------------------------------------

const HelloLicat = () => {
  const { name, id } = useContext(UserInfo);
  return (
    <div>
      <h2>{name}</h2>
      <strong>{id}</strong>
      <HelloLicatTwo/>
    </div>
  );
};

const HelloLicatTwo = () => {
  const { name, id } = useContext(UserInfo);
  return (
    <div>
      <h2>{name}</h2>
      <strong>{id}</strong>
    </div>
  );
};

export default App;

 

1.  createContext 를 import해준다.

 

2.  createContext로 UserInfo를 생성한다. 

 

3.  useContext (UserInfo) value 값을 name과 id에 구조분해 할당 해준다.

 

 

 

그밖에 파일이 분리되었을 경우에도 필요로 하는곳에 import하여 사용할 수 있다.

 

 

 


 

 

 

정리

 

기존엔 컴포넌트간에 상태를 교류할때는 부모 → 자식 흐름으로 props를 통해 전달해주었다.

 

하지만 자주 여기저기서 사용된다면 코드가 복잡해지고 불편해진다.

 

따라서 Context API 를통해 쉽게 상태를 교류할 수 있다.

 

 

그밖에 

 

Context를 사용하는 이유와 리덕스를 사용하는 이유는 비슷하다.

 

리덕스상태관리 라이브러리로 Context API 기반으로 만들어져 있으며 마찬가지로 전역 상태관리를 돕는다.