Provider와 value

어떤 컴포넌트에서 Provider로 감싸주면 그 하위에 있는 모든 컴포넌트들은 이 React Context에 저장되어 있는 전역 데이터에 접근할 수 있다. 자식 컴포넌트에게 props로 일일이 보내줄 필요가 없다는 것이 가장 큰 장점이다.

value는 context로 관리하고 싶은 데이터를 뜻한다. 이 value의 값을 prop으로 Provider 안에 넣어준다. 이를 통해서 context의 현재 값이 결정된다. 더 자세한 것은 아래에서...!

사용법

Context.js

import React, { createContext, useState } from "react";
import FunctionContextComponent from "./FunctionContextComponent";
import ClassContextComponent from "./ClassContextComponent";

export const ThemeContext = createContext(); // export 해 주어야 한다.

export default function Context() {
  const [darkTheme, setDarkTheme] = useState(true);

  function toggleTheme() {
    setDarkTheme((prevDarkTheme) => !prevDarkTheme);
  }

  return (
    <>
			{/* value로 전달해준 값을 useContext나 Consumer로 받을 수 있다. */}
      <ThemeContext.Provider value={darkTheme}>
        <button onClick={toggleTheme}>Toggle Theme</button>
        <FunctionContextComponent />
        <ClassContextComponent />
      </ThemeContext.Provider>
    </>
  );
}

ClassContextComponent.js

클래스 기반 컴포넌트에서는 Consumer를 이용하여 context를 관리할 수 있다.

import React, { Component } from "react";
import { ThemeContext } from "./Context";

export default class ClassContextComponent extends Component {
  themeStyles(dark) {
    return {
      backgroundColor: dark ? "#333" : "#CCC",
      color: dark ? "#CCC" : "#333",
      padding: "2rem",
      margin: "2rem",
    };
  }

  render() {
    return (
      <ThemeContext.Consumer> {/* Consumer 활용 */}
        {darkTheme => {  // value를 props으로 받아와 사용한다.
          return <div style={this.themeStyles(darkTheme)}>
            ClassTheme
          </div>
        }}
      </ThemeContext.Consumer>
    )
  }
}

FunctionContextComponent .js

함수 기반 컴포넌트에서는 Consumer를 사용하지 않고, useContext를 사용한다.

useContext를 사용하면 리턴 값으로 value로 전달받은 값을 사용할 수 있다. 위의 클래스 기반 컴포넌트의 사용법과 비교해봤을 때 엄청 코드가 간편해진 것을 확인할 수 있다.

import React, { useContext } from "react";
import { ThemeContext } from "./Context";

export default function FunctionContextComponent() {
  const darkTheme = useContext(ThemeContext); // useContext를 통해 ThemeContext의 value를 받아올 수 있다.
  
  const themeStyles = {
      backgroundColor: darkTheme ? "#333" : "#CCC",  // useContext로 받아온 state를 바로 적용 가능하다.
      color: darkTheme ? "#CCC" : "#333",
      padding: "2rem",
      margin: "2rem",
  }
  
  return <div style={themeStyles}>Function Theme</div>;
}

위의 방식을 좀 더 간편하게 하기 위해서 darkTheme이라는 state를 context로 관리할 수 있는 훅을 만들어보자.