[React] 컨텍스트 Context 알아보기

2023. 3. 22. 00:27WEB Dev/Javascript | REACT | Node.js

728x90

 

해당 내용은 SOAPLE 님의 처음 만난 리액트(React) 강좌에서 발췌하였습니다. 

 


 

 

📌 들어가며

 

리액트에서 상태관리를 할 수 있는 방법은 다양하게 존재한다. 상태관리 라이브러리를 쓰기 전에 리액트 내장 훅으로 사용할 수 있는 Context API에 대해서 공부해보고자 한다.

 

 

📌 context란

 

리액트 개별 컴포넌트들은 props를 통해 데이터를 전달한다. (부모 ➡️ 자식)

props를 통해 데이터를 전달하게 되면 다수의 컴포넌트에서 필요한 데이터는 Props Chain(Drilling) 현상이 일어난다.

 

이를 해결하기 위해 Context가 발전했다.

 

 

📌 context의 원리

 

리액트를 props 방식으로 운영할 때는 아래 그림과 같이 props를 props가 위치한 컴포넌트에서 필요한 컴포넌트까지 컴포넌트 트리를 타고 내려와야 한다.

 

 

 

 

그러나 상태관리 라이브러리 혹은 context를 사용하는 경우 필요한 데이터 "a"를 얻기 위해서는 한 번의 단계만 거치면 된다.

 

 

 

 

 

 

📌 context를 사용해야 하는 경우

 

여러 컴포넌트들이 접근해야 하는 데이터(ex 로그인 정보, UI 테마 등)

 

 

 

 

📌 context 사용 전 고려할 점

 

컴포넌트와 컨텍스트가 연동되면 재사용성이 떨어지게 된다.

따라서 여러 컴포넌트가 접근해야 하는 데이터가 아니면 props를 사용(Component Composition 방식)하는 것이 더 낫다.

 

 

 

📌 context 사용하기

 

 

1. 컨텍스트Context 생성

 

 

React에서 context 객체를 불러와야 하기 때문에 React를 import 해주고

React.createContext() 메소드를 통해 컨텍스트 객체를 생성한다.

 

 

import React from 'react';
const contextEX = React.createContext(기본데이터);

 

 

createContext의 인자로 기본 데이터를 넣어주게 되면 context 객체가 만들어진다.

리액트가 렌더링 될 때 context 객체를 구독하는 하위 컴포넌트가 나오면 현재 context의 값을 가장 가까이에 있는 상위 provider로부터 받아온다.

만약 상위에 provider가 없다면 객체에 들어가 있는 기본 데이터가 사용된다.

(기본값이 undefined면 기본값이 사용되지 않는다.)

 

 

 

 

2. 컨텍스트 프로바이더Context.Provider 생성

 

 

하위 컴포넌트들이 만들어진 컨텍스트 객체의 데이터를 받을 수 있도록 Context.provider를 만들어준다.

모든 컨텍스트 객체는 provider 컴포넌트를 가진다. 

context.provider 컴포넌트로 감싸진 하위 컴포넌트들이 해당 컨텍스트 데이터에 접근할 수 있다.

 

 

<ContextEX.Provider value={/* DATA */}>
</ContextEX.Provider>

 

 

위와 같이 provider 컴포넌트에는 value라는 속성이 있고, 이 속성의 값은 감싸진 하위 컴포넌트들에게 전달된다.

하위 컴포넌트들은 이 value의 값을 사용하게 되는데 이 때 데이터를 소비하는 컴포넌트를 Consuming Components 라고 한다.

 

 

 

 

 

이 하위 컴포넌트들은 컨텍스트 값의 변화를 지켜보다가 값이 변경되면 재렌더링 된다.

하나의 provider는 여러 개의 하위 컴포넌트와 연결될 수 있고 provider 컴포넌트는 중첩될 수 있다. 

(이 때 값의 변화는 Object.is 로 판별한다.)

 

 

* Context.consumer 컴포넌트 사용

 

 

컨텍스트를 데이터를 구독하기 위하여 consumer 컴포넌트를 사용한다. 

컴포넌트의 자식으로 함수를 넣고 (function as a child 방식 : 컴포넌트의 자식으로 함수를 사) 자식으로 들어간 함수가 현재 컨텍스트의 값을 받아서 리액트 노드로 리턴해준다.

함수로 전달된 value는 provider의 value 값이다.

상위에 provider가 없으면 createContext의 기본값과 같다.

 

 

<ContextEX.Consumer>
 {   (value) => {/* 값에 따라 컴포넌트 렌더링*/}    }
</ContextEX.Consumer>

 

 

* Context의 displayName 속성

 

 

context 객체는 displayName이라는 문자열 속성을 가진다. 

이 속성을 사용하면 브라우저 개발자 도구에서 provider나 consumer를 표시할 때 displayName을 같이 표시한다.

 

const ContextEX = React.createContext(기본값);
ContextEX.dsiplayName = '컨텍스트 사용 중';

 

 

 

 

📌 context 사용 시 주의할 사항

 

context는 재렌더링 할 때 레퍼런스 정보를 사용하기 때문에 provider 컴포넌트가 렌더링 될 때마다 모든 하위 컴포넌트가 재렌더링 된다.

 

이를 막기 위해 value 값을 하드코딩 하지 않고 state를 사용하여 불필요하게 재렌더링 되는 것을 제한한.

 

 

 

📌 context 여러 개 사용하기

 

 

provider 컴포넌트를 중첩해서 사용할 수 있다.

 

function Content () {
return <ThemeContext.Consumer>
        { theme => (
            <UserContext.Consumer>
                { user => (
                    <Profile user={user} theme={theme} />
                  )}
            <UserContext.Consumer>
          )}
    </ThemeContext.Consumer>
}

 

 

📌 context 을 useContext() 훅으로 사용하기

  

 

함수 컴포넌트에서 context를 사용하기 위해 매번 consumer 컴포넌트로 감싸줄 수 없다.

이를 위해서 useContext() 훅이 있다.

useContext를 사용하면 context 객체(값 아님)를 인자로 받아서 value 값을 변수에 저장할 수 있다.

이 값을 현재 컴포넌트에서 가장 가까운 provider 컴포넌트로부터 받아오게 된다.

context의 값이 변경되면 변경된 값과 함께 useContext 훅을 사용하는 컴포넌트가 재렌더링 된다.

 

function Content(){

const value = useContext(ContextEX);

    return (
    )

}

 

 

728x90