리액트를 공부하면서 쓰는 글이니 오류가 있을 수 있습니다. 있다면 알려주시면 감사하겠습니다!
이번에는 리액트 Context를 알아봅니다.
Context는 리액트 프로젝트에서 전역으로 사용되는 데이터를 이용할 때 사용되는 기능입니다. 애플리케이션 설정, 테마 같은 전역으로 공유되는 데이터를 이용할 때 유용합니다.
리액트를 하면서 데이터는 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달합니다. 하지만 Context를 사용하면 번거롭지 않게 부모에서 자식에게 데이터를 전달하지 않아도 됩니다.
Context를 사용하면 쉽게 데이터를 사용할 수 있지만 컴포넌트가 많고 복잡한 상황에서 Context를 사용하는 것이 좋습니다.
Context 생성하기
처음 Context 객체를 생성하려면 createContext() 메서드를 시용해 Context 객체를 만들 수 있습니다.
//ThemeContext.js
import { createContext } from "react";
const ThemeContext = createContext({
color: "skyblue"
});
export default ThemeContext;
createContext 메서드에 들어갈 인수는 생성한 Context에 기본 값입니다.
Context 값 사용하기
Context의 값을 사용하려면 createContext로 생성한 객체에서 Consumer 컴포넌트를 사용해야 합니다.
Consumer 컴포넌트는 자식을 함수로 받아 렌더링 합니다. 이 함수는 Context의 값을 이용해 렌더링 되어야 하는 엘리먼트를 반환해야 합니다.
//App.js
import React from "react";
import ThemeContext from "./ContextEx";
const App = () => {
return (
<div>
<ThemeContext.Consumer>
{value => (
<div>색상:{value.color}</div> //기본 값 skyblue
)}
</ThemeContext.Consumer>
</div>
)
}
export default App;
Consumer 컴포넌트의 Context 값은 Provider 컴포넌트가 가지고 있는 value 값과 같습니다. 만약 Provider 컴포넌트가 상위 컴포넌트에 없다면 값은 Context를 생성했을 때 지정한 기본 값이 사용됩니다.
Context 값 변경하기
Context 값을 변경하고 싶다면 Provider 컴포넌트를 사용해야 합니다. Provider 컴포넌트는 Context 값이 변경되면 Consumer 컴포넌트가 다시 렌더링 됩니다. Context 값의 변경은 Provider 컴포넌트의 value로 변경할 수 있습니다.
//App.js
import React from "react";
import ThemeContext from "./ContextEx";
const App = () => {
return (
<div>
<ThemeContext.Provider value={{ color: "green" }}>
<ThemeContext.Consumer>
{value => (
<div>색상:{value.color}</div> //green
)}
</ThemeContext.Consumer>
</ThemeContext.Provider>
</div>
)
}
export default App;
동적으로 Context 값 변경하기
클릭 같은 이벤트로 동적으로 값을 변경했을 때를 알아보겠습니다. Context를 생성할 때 컬러를 설정하는 빈 함수를 만들고 App 컴포넌트에서 useState를 이용해 state를 만들고 Provider 컴포넌트의 value에 state값과 변경 함수를 넣어주었습니다.
//ThemeContext.js
import { createContext } from "react";
const ThemeContext = createContext({
color: "skyblue",
setColor: () => {}
});
export default ThemeContext;
//ColorBtn.js
import React from "react";
import ThemeContext from "./ContextEx";
const ColorBtn = () => {
return (
<ThemeContext.Consumer>
{state => (
<div>
<div>색상:{state.color}</div>
<button onClick={() => state.setColor("green")}>클릭 하여 변경</button>
</div>
)}
</ThemeContext.Consumer>
)
}
export default ColorBtn;
//App.js
import React, { useState } from "react";
import ColorBtn from "./ColorBtn";
import ThemeContext from "./ContextEx";
const App = () => {
const [color, setColor] = useState("skyblue");
return (
<div>
<ThemeContext.Provider value={{ color: color, setColor:setColor }}>
<ColorBtn />
</ThemeContext.Provider>
</div>
)
}
export default App;
Provider에서 넘겨준 seColor 함수가 호출되면 state값인 color가 변경되면서 Provider의 value가 변경되므로 다시 렌더링 됩니다.
좀 더 편하게 Context 사용하기
Context 에도 훅이 존재하며 클래스형 컴포넌트를 이용하고 있다면 contextType을 이용하면 좀 더 편하게 Context를 사용할 수 있습니다.
contextType
contextType은 클래스형 컴포넌트에서 Context를 좀 더 쉽게 사용할 수 있도록 합니다.
contextType에 생성한 Context를 지정하면 클래스 내부에서 this.context를 이용해 Context 접근이 가능하며
static 변수로도 contextType을 사용할 수 있습니다.
//ColorBtn.js
import React, { Component } from "react";
import ThemeContext from "./ContextEx";
class ColorBtn extends Component {
// static contextType = ThemeContext;
render() {
return (
<div>
<div>색상:{this.context.color}</div>
<button onClick={() => this.context.setColor("green")}>
클릭 하여 변경
</button>
</div>
);
}
}
ColorBtn.contextType = ThemeContext;
export default ColorBtn;
하지만 contextType을 이용하면 여러 Context 사용이 불가능합니다. 따라서 여러 개를 이용해야 한다면 contextType을 사용하지 않거나 함수형 컴포넌트를 이용해 사용해야 합니다.
useContext() Hook
함수형 컴포넌트에서 useContext 훅을 사용하면 간단하게 Context를 사용할 수 있습니다. useContext의 값은 Hook을 호출하는 컴포넌트 중 가까이 있는 Provider의 value값입니다.
//ColorBtn.js
import React, { useContext } from "react";
import ThemeContext from "./ContextEx";
const ColorBtn = () => {
const context = useContext(ThemeContext);
return (
<div>
<div>색상:{context.color}</div>
<button onClick={() => context.setColor("green")}>
클릭 하여 변경
</button>
</div>
);
};
export default ColorBtn;
참고
리액트를 다루는 기술(개정판) - 김민준 지음
https://ko.reactjs.org/docs/context.html
'프로그래밍 > React' 카테고리의 다른 글
React(리액트) - redux 미들웨어 알아보기(redux-thunk, redux-saga) (0) | 2022.05.31 |
---|---|
React(리액트) - React Redux 알아보기 (0) | 2022.05.19 |
리액트(React)/라우터(Router) - Router 기초 (0) | 2022.05.10 |
리액트(React) - 리액트와 불변성 (0) | 2022.05.02 |
리액트(React) - Hooks 알아보기 (0) | 2022.04.27 |