React Context API 예제로 이해하기

React Context API 에 대하여 예제를 활용하여 이해하고 공부하는 내용입니다.

해당 책에 있는 내용을 배우고 공부하며 작성하는 글입니다.

그럼 차근차근 나열하겠습니다. 

예제 코드 1

				
					import { createContext } from "react";

const ColorContext = createContext({ color: "black" });

export default ColorContext;

				
			

먼저 위와 같은 컴포넌트를 특정 경로에 생성합니다.

				
					import ColorContext from "../Contexts/ColorContext";

const ColorBox = () => {
  return (
    <ColorContext.Consumer>
      {(value) => (
        <div
          style={{ width: "64px", height: "64px", background: value.color }}
        ></div>
      )}
    </ColorContext.Consumer>
  );
};

export default ColorBox;


				
			

그리고 방금 만든 ColorContext 를 가져와서 이렇게 사용할 수 있습니다.

일반적으로는 Chidren 이 있어야 할 자리에 JSX를 넣어주는 기법입니다.

이러한 기법을 Function as a child, 혹은 Render Props 라고 합니다. 

실제 페이지를 보면 요런 식으로 나타나는군요.

예제코드 2

앞선 예제는 단순이 특정 컴포넌트 내에 값을 할당하고, 그 값을 다른 컴포넌트에서 사용하는 방식이었습니다.

이번에는 어떤 값이 아니라, 어떤 동작을 위한 함수를 사용해보겠습니다.

				
					import { createContext, useState } from "react";

const ColorContext = createContext({
  state: { color: "black", subcolor: "red" },

  actions: { setColor: () => {}, setsubcolor: () => {} },
});

const ColorProvider = ({ children }) => {
  const [color, setColor] = useState("black");

  const [subcolor, setSubcolor] = useState("red");

  const value = {
    state: { color, subcolor },
    actions: { setColor, setSubcolor },
  };

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

//ColorContext.consumer 과 ColorConsumer 이 같은 뜻임
const { Consumer: ColorConsumer } = ColorContext;

// ColorProvider 과 ColorConsumer 내보내기
export { ColorProvider, ColorConsumer };

export default ColorContext;

				
			

위 코드에서 25번째 줄의 경우는 ColorContext.Consumer 을 ColorConsumer 라는 이름으로 사용할 수 있게 해주는 작업입니다.

이제 위 Context 를 어떻게 활용 가능한지 보겠습니다.

				
					import { ColorConsumer } from "../Contexts/ColorContext";

const ColorBox = () => {
  return (
    <ColorConsumer>
      {({ state }) => (
        <>
          <div
            style={{
              width: "64px",
              height: "64px",
              background: state.color,
            }}
          ></div>

          <div
            style={{
              width: "64px",
              height: "64px",
              background: state.subcolor,
            }}
          ></div>
        </>
      )}
    </ColorConsumer>
  );
};

export default ColorBox;


				
			

이런식으로 바로 ColorContext 내부에서 정의했던 state 라는 객체를 곧바로 사용이 가능합니다. 

만약 ColorConsumer 을 따로 지정하지 않았더라면, ColorContext.Consumer 을 사용해야겠죠.

예제코드 3

이제는 위에서 만들었던 ColorProvider 까지 사용을 해보겠습니다. 

				
					const ColorProvider = ({ children }) => {
  const [color, setColor] = useState("black");

  const [subcolor, setSubcolor] = useState("red");

  const value = {
    state: { color, subcolor },
    actions: { setColor, setSubcolor },
  };

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


				
			

ColorProvider 은 ColorContext 에 State 와 actions 를 전달하는 꼴을 하고 있습니다.

여기서 전달된 정보를 활용하여 Children 코드를 함께 나타냅니다. 

				
					const colors = ["red", "orange", "yellow", "green", "blue", "indigo", "pink"];

const SelectColors = () => {
  return (
    <div>
      <h1>색상을 선택하세요.</h1>

      <div style={{ display: "flex" }}>
        {colors.map((color, index) => (
          <div
            key={index}
            style={{
              background: color,
              width: "24px",
              height: "24px",
              cursor: "pointer",
            }}
          ></div>
        ))}
      </div>
    </div>
  );
};

export default SelectColors;


				
			

먼저 이런 식으로 클릭이 가능한 다양한 색깔의 사각형 div 를 주르륵 생성하는 컴포넌트를 만듭시다.

				
					        {/* React 공부 */}
        <Route
          path="/study"
          element={
            <ColorProvider>
              <div>
                <SelectColors />
                <ColorBox />
              </div>
            </ColorProvider>
          }
        />


				
			

요걸 이런 식으로 ColorProvider 내부에 감싸고, 그 내부에서 SelectColors 가 먼저 나타나고, 그 다음 ColorBox 가 나타날 수 있게 해봅시다.

위와 같은 느낌으로 생성이 됩니다.

여기서 윗 부분의 색을 선택하면 그 색으로 아래쪽 div 가 변경이 될 수 있도록 해봅시다.

				
					import { ColorConsumer } from "../Contexts/ColorContext";

const ColorBox = () => {
  return (
    <ColorConsumer>
      {({ state }) => (
        <>
          <div
            style={{
              width: "64px",
              height: "64px",
              background: state.color,
            }}
          ></div>

          <div
            style={{
              width: "64px",
              height: "64px",
              background: state.subcolor,
            }}
          ></div>
        </>
      )}
    </ColorConsumer>
  );
};

export default ColorBox;



				
			

기본적으로 ColorBox 는 ColorConsumer 을 통해서 state 내부에 설정된 color 과 subcolor 의 값을 가져옵니다.

SelectColors 에서 ColorContext 내부의 State 설정을 변경할 수 있다면 되겠군요.

				
					import { ColorConsumer } from "../Contexts/ColorContext";

const colors = ["red", "orange", "yellow", "green", "blue", "indigo", "pink"];

const SelectColors = () => {
  return (
    <div>
      <h1>색상을 선택하세요.</h1>

      <ColorConsumer>
        {({ actions }) => (
          <div style={{ display: "flex" }}>
            {colors.map((color, index) => (
              <div
                key={index}
                style={{
                  background: color,
                  width: "24px",
                  height: "24px",
                  cursor: "pointer",
                }}
                onClick={() => actions.setColor(color)}
              ></div>
            ))}
          </div>
        )}
      </ColorConsumer>
    </div>
  );
};

export default SelectColors;




				
			

요렇게 바꾸면 됩니다. 


그럼 이렇게 내가 선택한 컬러가 setColor 로 지정이 되어 state 내에 있는 color 의 값이 바뀝니다.

예제코드 4

이번에는 useContext 라는 Hook 을 사용해서 시행해보죠.

				
					import { useContext } from "react";
import ColorContext from "../Contexts/ColorContext";
import { ColorConsumer } from "../Contexts/ColorContext";

const ColorBox = () => {
  const { state } = useContext(ColorContext);

  return (
    <>
      <div
        style={{ width: "64px", height: "64px", backgroundColor: state.color }}
      />

      <div
        style={{
          width: "64px",
          height: "64px",
          backgroundColor: state.subcolor,
        }}
      />
    </>
  );
};

export default ColorBox;


				
			

이런 식으로 ColorConsumer 을 사용하지 않고, ColorContext 내에 있는 state 를 가져와서 사용이 가능합니다.

이러한 기법은 Class 컴포넌트가 아니라 함수 컴포넌트에만 사용이 가능합니다. 

마치며...

이렇게 ContextAPI 를 알아봤습니다.

사이트 내에서 공통적으로 이용해야 하는 Hook 이나 정보들이 있다면 이렇게 Context API를 사용하는 것도 좋은 방법입니다.