본문 바로가기

클라이언트/React
[리액트(React)] Context API

// Context API

- 전역적으로 데이터를 관리하고 접근하는 방법을 제공한다.

- props drilling을 해결할 수 있다.
   > 중간 컴포넌트를 거치지 않고 직접 데이터를 공유할 수 있다.
   > 레벨이 다른 컴포넌트 간에 데이터를 쉽게 주고받을 수 있게 해준다. 

- context 값을 생성하고, 제공하고, 여러 컴포넌트를 묶어준다.

- state와의 연결, 디버깅 등이 용이하다.


1. createContext 를 import한다.

import { createContext } from 'react';

2. 초기값을 할당하여 생성한다.

const 변수명 = createContext(초기값);


- 초기값을 undefined로 넣으면 초기값이 사용되지 않는다.

- 초기값을 사용하고자 하는 구조에 맞게 설정해두면 자동완성이 용이하다.


3. 외부에서 사용할 수 있도록 내보낸다.

export const context명 = createContext(초기값);


- context명은 대문자로 시작하도록 한다.


4. 해당 context 값을 사용할 위치에서 하위 컴포넌트들을 감싼다.

<context명.Provider value={값}>
    <하위 컴포넌트1 />
    <하위 컴포넌트2 />
</변수명.Provider>


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

- Provider 컴포넌트가 재렌더링되면 하위 consumer 컴포넌트도 모두 재렌더링 된다.


5. context 값을 사용한다.

const 변수명 = useContext(context명);


- useContext(): 함수형 컴포넌트에서 context를 쉽게 사용할 수 있게 해주는 Hook


또다른 사용 방법으로는 Consumer 가 있다.

<컴포넌트명.Consumer>
    {value => return}
</컴포넌트명.Consumer>


- 다소 복잡한 방식이라 추천하진 않지만, 옛 프로젝트에서 보일 수 있다.


※ 루트 컴포넌트에서 Context 작업을 하면 너무 복잡해질 수 있기 때문에, Context.Provider 컴포넌트를 따로 생성하는 것이 좋다.

export default function ContextProvider컴포넌트명({ children }) {

  //처리
  
  return (
    <Context명.Provider value={값}>{children}</Context명.Provider>
  );
}

export const CartContext = createContext({
  items: [],
  addItemToCart: () => {},
  updateItemQuantity: () => {},
});

export default function CartContextProvider({ children }) {
  const [shoppingCart, setShoppingCart] = useState({
    items: [],
  });

  function handleAddItemToCart(id) {
    //처리
  }

  function handleUpdateCartItemQuantity(productId, amount) {
    //처리
  }

  const ctxValue = {
    items: shoppingCart.items,
    addItemToCart: handleAddItemToCart,
    updateItemQuantity: handleUpdateCartItemQuantity,
  };

  return (
    <CartContext.Provider value={ctxValue}>{children}</CartContext.Provider>
  );
}

 

function App() {
  return (
    <CartContextProvider>
      <Header />
      <Shop />
    </CartContextProvider>
  );
}

export default App;

// Class.contextType
- 요즘은 거의 사용x
- Provider 하위에 있는 클래스 컴포넌트에서 context의 데이터에 접근하기 위해 사용

컴포넌트명.contextType = 컴포넌트명