본문 바로가기

FrontEnd

새로운 리액트 공식문서로 배우는 Context API 1편 : 프롭 드릴링 해결하기

반응형

원문 링크 : 

 
컨텍스트를 사용하면 부모 컴포넌트가 무언가를 props를 통해 명시적으로 전달하지 않아도
하위 컴포넌트가 얼마나 깊은 곳에 존재하는지 여부에 관계없이 하위 트리의 모든 컴포넌트에서 일부 정보를 사용할 수 있도록 합니다.

배울 내용
  • "프롭 드릴링"이란
  • 반복적인 prop 전달을 컨텍스트로 바꾸는 방법
  • 컨텍스트의 일반적인 사용 사례
  • 컨텍스트의 대안

"프롭 드릴링"이란

보통 공유 상태는 상위 컴포넌트로 올립니다.

이 경우 매우 아래에 있는 컴포넌트에 전달하기 곤란해 질 수 있죠.

이처럼 여러 단계에 거처 prop을 전달하는 것을 prop drilling이라 합니다.

props를 전달하지 않고 데이터를 필요로 하는 트리의 컴포넌트로 데이터를 "텔레포트"하는 방법이 있다면 좋지 않을까요?
React의 컨텍스트 기능을 사용하면 가능합니다!
컨텍스트를 사용하면 부모가 심지어 멀리 떨어져 있는 경우에도 내부 전체 트리에 어떤 데이터를 제공할 수 있습니다. 

 

컨텍스트 사용 방법

1. 컨텍스트를 만듭니다.

import { createContext } from 'react';

export const LevelContext = createContext(1);

2. 데이터를 Use하는 컴포넌트에서 해당 컨텍스트를 사용(use)합니다. 

useContext는 훅입니다.

useState 및 useReducer와 마찬가지로 React 구성 요소의 최상위 수준에서만 Hook을 호출할 수 있습니다.

export default function Heading({ children }) {
  const level = useContext(LevelContext);
  // ...
}

3. 데이터를 Provide하는 컴포넌트에서 해당 컨텍스트를 제공(Provide)합니다. 

데이터를 컨슘할 컴포넌트들을 프로바이더로 감쌉니다.

import { LevelContext } from './LevelContext.js';

export default function Section({ level, children }) {
  return (
    <section className="section">
      <LevelContext.Provider value={level}>
        {children}
      </LevelContext.Provider>
    </section>
  );
}

 

이것은 React에게 이렇게 말합니다 : "<Section> 내의 컴포넌트가 LevelContext를 요청하는 경우 데이터를 제공해주세요"

컴포넌트는 위의 UI 트리에서 가장 가까운 <LevelContext.Provider> 값을 사용합니다.

import { useContext } from 'react';
import { LevelContext } from './LevelContext.js';

export default function Section({ children }) {
  const level = useContext(LevelContext);
  return (
    <section className="section">
      <LevelContext.Provider value={level + 1}>
        {children}
      </LevelContext.Provider>
    </section>
  );
}

예를 들어, 해당 컴포넌트를 3중첩 할 경우,  3중첩 내부는 Default + 1 + 1 의 값을 받게 됩니다. 

컨텍스트는 다른 많은 사용 사례에도 유용합니다.
현재 색상 테마, 현재 로그인한 사용자 등 전체 하위 트리에 필요한 정보를 전달하는 데 사용할 수 있습니다.


컨텍스트는  중간에 해당 컨텍스트 데이터를 사용하지 않는 컴포넌트를 허용합니다.

그냥 쓰듯이 사용하면 됩니다.

또한 각 컨텍스트는 독립적으로 동작합니다. 서로를 재정의하지 않습니다.


컨텍스트를 사용하기 전에

몇 가지 props를 여러 깊이로 전달해야 한다고 해서 해당 정보를 컨텍스트에 넣어야 한다는 의미는 아닙니다.
컨텍스트를 사용하기 전에 고려해야 할 몇 가지 대안은 다음과 같습니다.
 

prop을 전달하여 시작합니다.

컴포넌트가 단순하지 않은 경우 수십 개의 컴포넌트에 수십 개의 prop을 전달하는 것은 드문 일이 아닙니다.
어떤 가 어떤 데이터를 사용하는지 매우 명확합니다!
코드를 유지 관리하는 사람은 props를 사용하여 데이터 흐름을 명시적으로 만들었다는 사실에 기뻐할 것입니다.

컴포넌트를 추출하여 자식을 children으로 전달합니다.

해당 데이터를 사용하지 않는 중간 컴포넌트 많은 계층을 통해 일부 데이터를 전달하는 경우(그리고 더 아래로만 전달하기만 하면),
이는 종종 도중에 일부 구성 요소를 추출하는 것을 잊었다는 의미입니다.
예를 들어 레이아웃 <Layout posts={posts} />와 같이
직접 사용하지 않는 시각적 컴포넌트에 게시물과 같은 데이터 소품을 전달할 수 있습니다.
대신 레이아웃이 children을 prop으로 사용하도록 만들고
<Layout><Posts posts={posts} /></Layout>을 렌더링합니다.
이렇게 하면 데이터를 지정하는 컴포넌트와 이를 필요로 하는 컴포넌트 사이의 계층 수가 줄어듭니다.
 
이러한 접근 방식 중 어느 것도 자신에게 적합하지 않은 경우 컨텍스트를 고려하십시오.

컨텍스트 사용 사례

  • 테마 : 다크모드 여부, 다크모드 변경
  • 현재 로그인한 계정
  • 라우팅 : 대부분의 라우팅 솔루션은 내부적으로 컨텍스트  API를 사용중
  • 상태 관리 : 뒤에 좀 더 알아봄
컨텍스트는 정적 값으로 제한되지 않습니다.
다음 렌더에서 다른 값을 전달하면 React는 컨텍스트 아래의 모든 컴포넌트를 업데이트 합니다.
이것이 컨텍스트가 종종 상태와 함께 사용되는 이유입니다.
트리의 다른 부분에 있는 멀리 떨어진 컴포넌트에 전달할 기능, 정보가 필요한 경우 컨텍스트가 도움이 될 것이라는 좋은 표시입니다.

요약

컨텍스트를 사용하면 컴포넌트가 그 아래 전체 트리에 정보를 제공할 수 있습니다.

컨텍스트를 전달하려면

  • 1. export const MyContext = createContext(defaultValue)로 생성하고 내보냅니다.
  • 2. useContext(MyContext) Hook에 전달하여 아무리 깊더라도 자식 컴포넌트에서 읽습니다.
  • 3. 자식을 <MyContext.Provider value={...}>로 래핑하여 부모로부터 제공합니다.
컨텍스트는 중간에 있는 모든 컴포넌트를 통과합니다.
컨텍스트를 사용하면 "주변 환경에 순응/적응/반응하는" 컴포넌트를 작성할 수 있습니다. (정보 공유를 통해)
컨텍스트를 사용하기 전에 먼저 props를 전달하거나 JSX를 children으로 전달해 보세요
 
 

 

 

반응형