- Context API는 리액트 프로젝트에서 전역적으로 사용할 데이터가 있을 때 유용한 기능
- 사용 예
- 로그인 정보
- 애프리케이션 환경 설정
- 테마
- redux, react-router, styled-components 의 라이브러리
- 컴포넌트 간에 데이터를 props로 저달하기 때문에 여기저기서 필요한 데이터가 있을 때는 주로 최상위 컴포넌트인 App의 state에 넣어서 관리
- 하지만 props으로 아주 ~ 먼 컴포넌트에 전달하려면 여러개의 컴포넌트를 지나가야 하니... 유지 보수성이 낮아질 가능성이 있음
- 위 문제점을 해결하기 위해서 redux나 MobX 같은 상태 관리 라이브러리를 사용하면 전역 상태 관리를 더 편하게 처리
- 리액트 v16.3 업데이트 이후에는
Context API
가 많이 개선되었기 때문에 별도의 라이브러리 사용할 필요 없음
import { createContext } from 'react';
const ColorContext = createContext({ color: 'black' });
export default ColorContext;
import ColorBox from './components/ColorBox';
<ColorBox></ColorBox>
Provider 이용하기
Provider
를 사용하면 Context의 값을 변경할 수 있다.- 아래와 같이 컴포넌트
ColorBox
를ColorContext.Provider
를 통해 color 값을 변경할 수 있다. - Provider를 사용할때는 value 값을 명시해줘야 제대로 작동
<ColorContext.Provider value={{ color: 'red' }}>
<div>
<ColorBox></ColorBox>
</div>
</ColorContext.Provider>
동적으로 사용하기
- context의 value에는 상태값, 함수를 전달할 수 있다.
- 아래와 같이 state, actions을 따로 정의한
ColorContext
를 정의 ColorProvider
를 정의
import React, { createContext, useState } from 'react';
// 객체에서 state, actions을 분리해서 정의하면 나중에 사용하기가 편함
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;
import React from 'react';
import { ColorConsumer } from '../contexts/color';
const ColorBox = () => {
return (
<ColorConsumer>
{(
{ state } // 객체 비구조화 할당 문법
) => (
<>
<div
style={{
width: '64px',
height: '64px',
background: state.color
}}
/>
<div
style={{
width: '32px',
height: '32px',
background: state.subcolor
}}
/>
</>
)}
</ColorConsumer>
);
};
export default ColorBox;
사용하는 쪽에서는 아래와 같이
<ColorProvider>
<div>
<ColorBox></ColorBox>
</div>
</ColorProvider>
색상 선택하는 컴포넌트 생성
Context
에 들어있는actions
에 넣어준 함수를 호출하는 컴포넌트 생성
# SelectColor.js
import React from 'react';
import { ColorConsumer } from '../contexts/color';
const colors = [
'red',
'oragne',
'yellow',
'green',
'blue',
'indigo',
'violoet'
];
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;
App.js
에서는SelectColors
의 컴포넌트를 추가
<ColorProvider>
<div>
<SelectColors></SelectColors>
<ColorBox></ColorBox>
</div>
</ColorProvider>
useContext Hook 사용
- 리액트 내장되어 있는 Hooks 중에서 useContext를 사용해보자
useContext
Hook은 함수형 컴포넌트에서만 사용할 수 있다.ColorBox
를 아래와 같이 수정
import React, { useContext } from 'react';
import { ColorContext } 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를 좀 더 쉽게 사용하기 위해서 static contextType을 정의
- 기존에
SelectColors
의 컴포넌트를 클래스형으로 변경 - static contextType을 정의하면 클래스 메소드에서도 Context에 있는 함수 호출이 가능
- 단점이라면 한 클래스에서 하나의 context만 사용할 수 있음
useContext
를 사용하는게 더 권장됨- 아래가 기존
import React from 'react';
import { ColorConsumer } from '../contexts/color';
const colors = [
'red',
'oragne',
'yellow',
'green',
'blue',
'indigo',
'violoet'
];
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;
- 이후가 클래스 컴포넌트로 변경 후
import React, { Component } from 'react';
import ColorContext from '../contexts/color';
const colors = [
'red',
'oragne',
'yellow',
'green',
'blue',
'indigo',
'violoet'
];
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;
'Web 개발 > React' 카테고리의 다른 글
[React] react-helmet-async로 meta태그 설정 (0) | 2020.02.18 |
---|---|
[React] qs 라이브러리 사용해서 posts 리스트 가져오는 작업순서 정리 (0) | 2020.02.18 |
[React] UI 만들기 styled-components (0) | 2020.02.10 |
[React] axios 사용 예제 코드 (0) | 2020.02.10 |
[React] REST API 개발 전에 JSONPlaceholder 이용해 JSON 데이터 샘플 호출해서 가져오기 (0) | 2020.02.10 |