[React] Context API
리액트 프로젝트 내에 전역적으로 관리할 데이터가 있을 때 Context API를 사용한다.
예를 들면 사용자 로그인 정보, 애플리케이션 환경 설정, 테마 등
리액트 라이브러리로 리덕스, 리액트 라우터, styled-components 도 Context API를 기반으로 구현되어 있음
전역적으로 관리할 데이터는 주로 최상위 컴포넌트인 App의 state에 넣어서 관리함
예제)
마우스 클릭에 따라 색상 바뀌는것
왼쪽은 큰 정사각형, 오른쪽은 작은 정사각형 색이 변함
오른쪽 마우스 클릭은 onContextMenu를 사용! 왼쪽 마우스는 OnClick
components/ColorBox.js
import React from "react";
import { ColorConsumer } from "../contexts/color";
const ColorBox = () => {
return (
<ColorConsumer>
{(value) => (
<>
<div
style={{
width: "64px",
height: "64px",
background: value.state.color,
}}
/>
<div
style={{
width: "32px",
height: "32px",
background: value.state.subcolor,
}}
/>
</>
)}
</ColorConsumer>
);
};
export default ColorBox;
components/SelectColor.js
import React from "react";
import { ColorConsumer } from "../contexts/color";
const colors = ["red", "orange", "yellow", "green", "blue", "indigo", "violet"];
const SelectColors = () => {
return (
<div>
<h2> 색상을 선택하세요.</h2>
<ColorConsumer>
{({ actions }) => (
<div style={{ display: "flex" }}>
{colors.map((color) => (
<div
key={color}
style={{
background: color,
width: "24px",
height: "24px",
cursor: "pointer",
}}
onClick={() => actions.setColor(color)}
onContextMenu={(e) => {
e.preventDefault();
actions.setSubcolor(color);
}}
/>
))}
</div>
)}
</ColorConsumer>
<hr />
</div>
);
};
export default SelectColors;
contexts/color.js
import { createContext } from "react";
import React, { 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>
);
};
const { Consumer: ColorConsumer } = ColorContext;
export { ColorProvider, ColorConsumer };
export default ColorContext;
App.js
import logo from "./logo.svg";
import "./App.css";
import ColorBox from "./components/ColorBox";
import { ColorProvider } from "./contexts/color";
import SelectColors from "./components/SelectColor";
function App() {
return (
<ColorProvider>
<div>
<SelectColors />
<ColorBox />
</div>
</ColorProvider>
);
}
export default App;
useContext Hook 사용
components/ColorBox.js
import React, { useContext } from "react";
import ColorContext from "../contexts/color";
import { ColorConsumer } from "../contexts/color";
const ColorBox = () => {
const { state } = useContext(ColorContext);
return (
<>
<div
style={{
width: "64px",
height: "64px",
background: state.color,
}}
/>
<div
style={{
width: "32px",
height: "32px",
background: state.subcolor,
}}
/>
</>
);
};
export default ColorBox;
클래스형 컴포넌트로 static contextType 사용
장점 : 클래스 메서드에서도 Context에 넣어 둔 함수를 호출할 수 있다.
단점 : 한 클래스에서 하나의 Context밖에 사용하지 못한다.
useContext사용을 권장
components/SelectColor.js
import React, { Component } from "react";
import ColorContext from "../contexts/color";
const colors = ["red", "orange", "yellow", "green", "blue", "indigo", "violet"];
class SelectColors extends Component {
static contextType = ColorContext;
handleSetColor = (color) => {
this.context.actions.setColor(color);
};
handleSetSubcolor = (subcolor) => {
this.context.actions.setSubcolor(subcolor);
};
render() {
return (
<div>
<h2> 색상을 선택하세요.</h2>
<div style={{ display: "flex" }}>
{colors.map((color) => (
<div
key={color}
style={{
background: color,
width: "24px",
height: "24px",
cursor: "pointer",
}}
onClick={() => this.handleSetColor(color)}
onContextMenu={(e) => {
e.preventDefault();
this.handleSetSubcolor(color);
}}
/>
))}
</div>
<hr />
</div>
);
}
}
export default SelectColors;