[React] Context API

수민🐣·2023년 2월 16일
0

React

목록 보기
25/36

Context API

React에서 제공하는 내장 API

컴포넌트들에게 동일한 Context(맥락)을 전달하는데 사용할 수 있다.

리액트에서 데이터를 전달하는 기본 원칙은 단방향성

즉, 부모 컴포넌트에서 자식 컴포넌트 방향으로만 데이터를 전달할 수 있다는 의미

➡ 애플리케이션의 안전성을 높이고 흐름을 단순화하는데 유용하지만 때때로 너무 많은 단계를 거쳐서 자식 컴포넌트에 데이터를 전달해야 한다는 문제점을 야기

➡ Props를 사용하지 않아도 특정 값이 필요한 컴포넌트끼리 쉽게 값을 공유할 수 있게 한다.
➡ 주로 프로젝트에서 전역 상태를 관리할 때 많이 사용 한다.

① Context 생성

기본 값을 설정하고 싶다면, createContext 함수에 인자로 기본 값을 넣어주시면 된다.

const MyContext = createContext();

const MyContext = createContext('default value');

만약, 기본 값을 보여주지 않고 아예 오류를 띄워서 개발자가 고치도록 명시를 하고 싶다면

const MyContext = createContext();

function useMyContext() {
  const value = useContext(MyContext);
  if (value === undefined) {
    throw new Error('useMyContext should be used within MyContext.Provider');
  }
}

② .Provider .Consumer

context 객체를 만들면 ~.Provider 컴포넌트와 ~.Consumer라는 컴포넌트가 만들어진다.

  • Provider
    Context 안에 있는 값을 사용할 컴포넌트들을 감싸주는 용도로 사용한다.

    • value
      Context를 통해 여러 컴포넌트에서 공유할 수 있는 값

      즉, 컴포넌트간에 공유하고자 하는 값을 value 라는 Props로 설정하면 자식 컴포넌트들에서 해당 값에 바로 접근을 할 수 있습니다.

function App() {
  return (
    <NavigationContainer>
      <LogContext.Provider value="Hello World">
        <FeedsStack />
      </LogContext.Provider>
    </NavigationContainer>
  );
}

export default App;

➡ 이렇게 Provider 컴포넌트를 사용하면 이 컴포넌트 내부에 선언된 모든 컴포넌트에서 Context안의 값을 사용할 수 있다.

  • Consumer
    Context 안의 값을 사용할 때 사용한다.
function FeedsStack() {
  return (
    <View>
      <LogContext.Consumer>
        {(value) => <Text>{value}</Text>}
      </LogContext.Consumer>
    </View>
  )
}

export default FeedsStack;

③ useContext

원하는 컴포넌트에서 useContext 라는 Hook을 사용하여 Context에 넣은 값에 바로 접근할 수 있다.

const MyContext = createContext();
const value = useContext(MyContext);

➡ 각 컴포넌트에서 원하는 값을 useContext로 가져오는 방식

➡ value 값이 바뀔 경우, useContext를 사용한 모든 컴포넌트들이 리렌더링

// 예시
import { createContext, useContext } from 'react';
const MyContext = createContext();

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

function AwesomeComponent() {
  return (
    <div>
      <FirstComponent />
      <SecondComponent />
      <ThirdComponent />
    </div>
  );
}

function FirstComponent() {
  const value = useContext(MyContext);
  return <div>First Component says: "{value}"</div>; 
} // First Component says: Hello World

function SecondComponent() {
  const value = useContext(MyContext);
  return <div>Second Component says: "{value}"</div>;
} // Second Component says: Hello World

function ThirdComponent() {
  const value = useContext(MyContext);
  return <div>Third Component says: "{value}"</div>;
} // Third Component says: Hello World

export default App;

전역 상태 관리 라이브러리는 언제 써야 할까?

Context는 전역 상태 관리를 할 수 있는 수단일 뿐이고, 상태 관리 라이브러리는 상태 관리를 더욱 편하고, 효율적으로 할 수 있게 해주는 기능들을 제공해주는 도구

예를 들어, Redux의 경우에는 액션과 리듀서라는 개념을 사용하여 상태 업데이트 로직을 컴포넌트 밖으로 분리 할 수 있게 해주며, 상태가 업데이트 될 때 실제로 의존하는 값이 바뀔 때만 컴포넌트가 리렌더링 되도록 최적화를 해준다. 만약 Context를 쓴다면, 각기 다른 상태마다 새롭게 Context를 만들어주어야 하는데, 이 과정을 생략할 수 있기에 편리하다.

MobX의 경우엔 Redux와 마찬가지로 상태 업데이트 로직을 컴포넌트 밖으로 분리할 수 있게 해주고, 함수형 리액티브 프로그래밍 방식을 도입하여 mutable한 상태가 리액트에서도 잘 보여지게 해주고 상태 업데이트 로직을 더욱 편하게 작성할 수 있게 해주며 최적화도 잘 해준다.

Recoil, Jotai, Zustand의 경우엔 Context를 일일이 만드는 과정을 생략하고 Hook 기반으로 아주 편하게 전역 상태 관리를 할 수 있게 해주죠. 최적화 기능 또한 덤으로 딸려온다.

즉, 전역 상태 라이브러리는 결국 상태 관리를 조금 더 쉽게 하기 위해서 사용하는 것이며 취향에 따라 선택해서 사용하면 되는 것

0개의 댓글