context를 이용하면 단계마다 일일이 props를 넘겨주지 않고도 컴포넌트 트리 전체에 데이터를 제공할 수 있습니다.
Context를 써야 하는 이유
1. props을 명시적으로 넘겨주고 있는 예시
class App extends React.Component {
render() {
return <Toolbar theme="dark" />;
}
}
function Toolbar(props) {
// Toolbar 컴포넌트는 불필요한 테마 prop를 받아서 ThemeButton에 전달해야 합니다.
// 앱 안의 모든 버튼이 테마를 알아야 한다면 이 정보를 일일이 넘기는 과정은 매우 곤혹스러울 수 있습니다.
return (
<div>
<ThemedButton theme={props.theme} />
</div>
);
}
class ThemedButton extends React.Component {
render() {
return <Button theme={this.props.theme} />;
}
}
- Props(Properties): 부모 컴포넌트와 자식 컴포넌트 또는 한 컴포넌트 안에서 데이터를 다루기 위해 사용
- 즉, 위에서 아래로 데이터가 흐름
- 흐름을 비교적 알기 쉬워서 이해가 빠르게 된다는 장점
- 여러 레벨 존재 시 → 매번 공통 부모 컴포넌트를 수정하고 하위 모든 컴포넌트에 데이터를 props로 전달하는 것은 매우 비효율적이라는 단점
2. context를 사용한 예시
- 부모 컴포넌트로부터 자식 컴포넌트로 전달되는 데이터의 흐름과는 상관 없이 전역적(global)인 데이터를 다룰 때 사용
- context를 사용하면 중간에 있는 엘리먼트들에게 props를 넘겨주지 않아도 됨.
- 전역 데이터를 context에 저장한 후, 데이터가 필요한 컴포넌트에서 해당 데이터를 불러와 사용
// context를 사용하면 모든 컴포넌트를 일일이 통하지 않고도
// 원하는 값을 컴포넌트 트리 깊숙한 곳까지 보낼 수 있습니다.
// light를 기본값으로 하는 테마 context를 만들어 봅시다.
const ThemeContext = React.createContext('light');
class App extends React.Component {
render() {
// Provider를 이용해 하위 트리에 테마 값을 보내줍니다.
// 아무리 깊숙히 있어도, 모든 컴포넌트가 이 값을 읽을 수 있습니다.
// 아래 예시에서는 dark를 현재 선택된 테마 값으로 보내고 있습니다.
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
}
// 이젠 중간에 있는 컴포넌트가 일일이 테마를 넘겨줄 필요가 없습니다.
function Toolbar() {
return (
<div>
<ThemedButton />
</div>
);
}
class ThemedButton extends React.Component {
// 현재 선택된 테마 값을 읽기 위해 contextType을 지정합니다.
// React는 가장 가까이 있는 테마 Provider를 찾아 그 값을 사용할 것입니다.
// 이 예시에서 현재 선택된 테마는 dark입니다.
static contextType = ThemeContext;
render() {
return <Button theme={this.context} />;
}
}
Context API
React에서 context를 사용하기 위해서는 context api를 사용해야 하며, Context의 Provider와 Consumer를 사용해야 합니다.
- 공통 부모 컴포넌트에 Context의 Provider를 사용하여 데이터 제공
- 데이터를 사용하려는 컴포넌트에서 Context의 Consumer를 사용하여 실제로 데이터를 사용
- 로그인 데이터, 웹 내 사용자가 쓰는 설정 파일, 테마, 언어 등 다양하게 컴포넌트간 공유되어야 할 데이터로 사용하면 좋음
Context 사용법
React.createContext
import { createContext } from "react";
const MyContext = createContext(defaultValue);
React에서 Context를 생성하기 위해서는 createContext를 사용하여 Context를 생성
defaultValue
→ 전역 변수로 사용될 데이터의 초기값을 설정
→ 트리 안에서 적절한 Provider를 찾지 못했을 때만 쓰이는 값
Context.Provider
<MyContext.Provider value={/* 어떤 값 */}>
class App extends Component {
render() {
return (
<MyContext.Provider value={/* 어떤 값 */}>
<Button/>
<Title />
<Message />
</MyContext.Provider>
);
}
}
Context를 사용하여 전역 데이터를 사용하려면 공통 부모 컴포넌트에 Context의 Provider를 사용
Provider를 전달하는 변수는 꼭 value를 사용해야 함
전달받는 컴포넌트의 제한 수는 없음
provider에 하위 provider 배치가 가능하며, 그럴 경우 하위 provider 값이 우선시됨
Provider로 감싼 후, 그 하위에 있는 모든 컴포넌트(Button, Title, Message)
→ Provider의 value는 하위의 모든 컴포넌트에서 사용 가능
→ value 속성값을 지정하지 않았을 경우, context를 생성할 때 넘겼던 디폴트 값이 사용됨.
전역 데이터를 하위 컴포넌트에서 접근하는 방법
Consumer로 Context 접근하기
- Provide의 value의 변경 사항을 구독
- context에서 가장 가까운 provider의 value를 참조함
- 단, 이 방법은 함수 컴포넌트에서만 사용 가능
import React from "react";
import MyContext from "./MyContext"
function Title() {
return (
<MyContext.Consumer>
{(lang) => {
const text = lang;
return <h1>{text}</h1>;
}}
</MyContext.Consumer>
);
}
useContext로 Context 접근하기
- Hook의 useContext로 Context 객체의 value 가져올 수 있음
- 단, 이 방법은 함수 컴포넌트에서만 사용 가능
import React, { useContext } from "react";
import MyContext from "./MyContext";
function Button() {
const lang = useContext(MyContext);
return <button>{lang}</button>;
}
contextType으로 Context 접근하기
- Class의 contextType에 Context 객체 할당 가능
- this.context로 해당 Context의 value 참조 가능
- 단, 이 방법은 클래스 컴포넌트에서만 사용 가능
import React, { Component } from "react";
import MyContext from "./MyContext";
class Message extends Component {
static contextType = MyContext;
render() {
const num = this.context;
if (num === 1)
return (
<p>
"Context provides a way to pass data through the component tree
without having to pass props down manually at every level"
</p>
);
else
return (
<p>
"컨텍스트는 모든 레벨에서 일일이 props를 넘기지 않고도 컴포넌트 트리에
걸쳐서 데이터를 전달할 수 있는 방법을 제공합니다."
</p>
);
}
}
context API 장단점
장점
- 기존에는 컴포넌트 간에 상태를 교로해야 하는 경우 무조건 부모 → 자식 흐름으로 props를 통해 전달해주었지만, Context API를 통해 더욱 쉽게 상태를 고류할 수 있게 됨
- 프로젝트의 컴포넌트 구조가 복잡하고 전역적으로 많이 사용되는 데이터가 많으며, 컴포넌트 개수가 많다면 Context API 사용
단점
- context api에서 상태 값을 변경하면, provider로 감싼 모든 자식 컴포넌트들이 리렌더링 됨.(업데이트)
- React context를 사용하면 해당 컴포넌트는 해당 context가 없이는 재사용이 불가능
- 따라서 단순하고 다루는 상태의 종류가 적다면 사용하지 말자!
참고 블로그
https://dev-yakuza.posstree.com/ko/react/context-api/
https://ko.reactjs.org/docs/context.html
'프로그래밍 언어 > React' 카테고리의 다른 글
FCMToken이란? (1) (0) | 2022.11.18 |
---|---|
Javascript VS Typescript (0) | 2022.11.07 |
React : cookie / localStorage / SessionStorage (0) | 2022.05.17 |
React의 기초 (0) | 2021.08.11 |
자바스크립트의 기초 (0) | 2021.08.11 |