기존에는 프로젝트 내에서 환경 설정, 사용자 정보와 같은 전역적으로 필요한 상태를 관리해야할 때 최상위 컴포넌트에서 여러 컴포넌트를 거쳐 props로 원하는 상태와 함수를 전달했지만, Context API를 사용하면 Context를 만들어 단 한번에 원하는 값을 받아와 사용할 수 있음.
새 Context 만들기
새 Context를 만들 때는 CreateContext 함수를 사용한다. 파라미터에는 해당 Context의 기본 상태를 지정한다.
import {createContext} from 'react';
const ColorContext = createContext({color: 'black'});
export default ColorContext;
Consumer 사용하기
ColorContext 안에 있는 들어있는 Consumer 라는 컴포넌트를 통해 색상을 조회할 수 있다.
const ColorBox = () => {
return (
<ColorContext.Consumer>
{value => (
<div
style={{
width: '64px',
height: '64px',
background: value.color
}}
/>
)}
</ColorContext.Consumer>
);
};
Consumer 사이에 중괄호를 열어서 그 안에 함수를 넣어준 것처럼, 컴포넌트의 children이 있어야 할 자리에
일반 JSX 혹은 문자열이 아닌 함수를 전달하는 것을 Function as a child, 혹은 Render Props라고 한다.
/*Render Props 예제*/
const RenderPropsSample = ({childern}) => {
return <div> 결과: {children(5)}</div>;
};
...
<RenderPropsSample>{value => 2 * value}</RenderPropsSample>;
/*RenderPropsSample에게 children props로 파라미터에 2를 곱해서 반환하는 함수를 전달하면
해당 컴포넌트에서는 이 함수에 5를 인자로 넣어서 "결과: 10"을 렌더링한다.*/
Provider
Provider를 사용하면 Context의 value를 변경할 수 있다.
<ColorContext.Provider value={{color: 'red'}}>
<div>
<ColorBox />
</div>
</ColorContext.Provider>
useContext Hook
import React, {useContext} from 'react';
import ColorContext from '../contexts/color';
const ColorBox = () => {
const {state} = useContext(ColorContext);
return(
<div>
<div
style={{
width: '64px',
height: '64px',
background: state.color
}}
/>
<div
style={{
width: '32px',
height: '32px',
background: state.subcolor
}}
/>
</div>
);
};
export default ColorBox;
함수형 컴포넌트에서 Context의 Consumer 컴포넌트와 Render Props 패턴을 사용하지 않고,
useContext Hook 사용하여 훨씬 편하게 Context 값을 조회할 수 있다.
static contextType
imort 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>
<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>
);
}
}
static contextType을 정의하면 this.context를 조회했을 때 현재 Context의 value를 가리키게 되고,
클래스 메서드에서도 Context에 넣어둔 함수를 호출할 수 있다.
하지만, 한 클래스에서 하나의 Context 밖에 사용하지 못한다는 단점이 있다.