Context API

hyocho·2023년 2월 6일
0

React

목록 보기
5/24
post-thumbnail

👻Context란?

  1. 리액트 컴포넌트간에 어떠한 값을 공유할 수 있게 해주는 기능.
  2. 주로 전역적으로 필요한 값을 다룰 때 사용.
  3. Props 방식이 아닌 다른 방식으로 컴포넌트간에 값을 전달하는 방법.

언제 사용하면 좋을까?

로그인 데이터, 웹 내 사용자가 쓰는 설정파일, 테마, 언어, nav에서 로그인된 상태의 화면등 context를 사용하면 편리하게 코드를 관리할 수 있다.

context 사용법

리액트 패키지에서 createContext 함수를 불러와서 변수에 담고 인자로 기본값을 준다.

import { createContext } from 'react';
const MyContext = createContext();

Context 객체 안에는 Provider라는 이름의 컴포넌트가 들어있다. 그 컴포넌트간에 공유하고자 하는 값을 value라는 Props로 설정하면 자식 컴포넌트들에서 해당 값에 바로 접근할 수 있다.

Context에 저장된 데이터를 사용하기 위해서는 공통 부모 컴포넌트에 Context의 Provider를 사용하여 데이터를 제공해야 한다.

function App() {
  return (
    <MyContext.Provider value="Hello World">
      <GrandParent />
    </MyContext.Provider>
  );
}

이렇게 하면 원하는 컴포넌트에서 useContext라는 Hook을 사용하여 Context에 넣은 값에 바로 접근할 수 있다.
해당 Hook의 인자에는 createContext로 만든 Mycontext를 넣는다.

import { createContext, useContext } from 'react';

function Message() {
  const value = useContext(MyContext);
  return <div>Received: {value}</div>;
}

Provider 하위에서 context를 구독하는 모든 컴포넌트는 Provider의 value prop가 바뀔 때마다 다시 렌더링 된다.

TL;DR

1.createContext() 함수를 사용하여 Context 만들기
2.최상위 컴포넌트에서 Provider로 감싸기
3.하위 컴포넌트에서 context API 설정하기

Provider를 사용하지 않을 경우

value값을 따로 지정하지 않았기 때문에 undefined로 조회된다.
기본값을 설정하고 싶다면 createContext함수에 인자로 기본 값을 넣어주면 된다.

const MyContext = createContext('default value');

Context에서 상태 관리가 필요한 경우

Provider를 새로 만들어 주는 것이 좋다.

import { createContext } from 'react';

const CounterContext = createContext();

function CounterProvider({ children }) {
  return <CounterContext.Provider>{children}</CounterContext.Provider>;
}

function App() {
  return (
    <CounterProvider>
      <div>
        <Value />
        <Buttons />
      </div>
    </CounterProvider>
  );
}

// (...)

children Props를 받아와서 CounterContext.Provider 태그 사이에 넣어주면 된다. 그 다음엔 필요한 기능들을 CounterProvider 컴포넌트 안에서 구현해주면 된다.

파일을 따로 분리하는 방법

Context를 이렇게 따로따로 작성하지 않고 하나의 context.js 파일을 만들어서 관리할 수도 있다.

import * as React from 'react'

const CountContext = React.createContext()

function countReducer(state, action) {
  switch (action.type) {
    case 'increment': {
      return {count: state.count + 1}
    }
    case 'decrement': {
      return {count: state.count - 1}
    }
    default: {
      throw new Error(`Unhandled action type: ${action.type}`)
    }
  }
}

// Custom Provider
function CountProvider({children}) {
  const [state, dispatch] = React.useReducer(countReducer, {count: 0})
  const value = {state, dispatch}
  return <CountContext.Provider value={value}>{children}</CountContext.Provider>
}

// Custom Consumer
function useCount() {
  const context = React.useContext(CountContext)
  if (context === undefined) {
    throw new Error('useCount must be used within a CountProvider')
  }
  return context
}

// 최상단 컴포넌트에서 Custom Provider를, 각 컴포넌트에서 이 Custom Consumer를 사용할 수 있다.
export {CountProvider, useCount}

Context 의 문제점

컴포넌트에 context가 연결되면 재사용성이 떨어지므로 꼭 필요한 곳에만 사용하도록 한다.

Redux 와의 차이점

Context API는 상태 관리 도구가 아니며 상태 관리 자체는 직접 관리해야한다. Context API는 그저 전역적으로 상태를 공유(상태가 아니더라도 데이터(값)이라면 무엇이든) 해주는 기능만 수행한다. Context API는 useState,useReducer를 통해 직접 상태관리를 하는 함수들을 props없이 전달해주는 것 뿐이다.
그에 반해 Redux는 상태를 관리해준다.

😮여기서 상태 관리란 ?
초기 값을 저장한다.
현재 값을 읽을 수 있다.
값 업데이트가 가능하다.

profile
기록하는 습관을 기르고 있습니다.

0개의 댓글