context를 이용하면 단계마다 일일이 props를 넘겨주지 않고도 컴포넌트 트리 전체에 데이터를 제공할 수 있습니다.
리액트에서는 부모 컴포넌트와 자식 컴포넌트간에 데이터를 전달할 수 있는데, 데이터를 전달할 때 부모에서 자식에게로만 데이터가 전달이 가능하다.
이러한 단방향 데이터 흐름에서 부모-자식간의 교류가 아닌 컴포넌트간의 데이터 교류. 즉 자식간의 교류가 필요한 경우 글로벌 상태 관리를 하기 위해 상태 관리 라이브러리가 등장!
그래서 리액트의 context를 사용하여 props를 넘겨주지 않고 컴포넌트 간의 값을 공유할 수 있다.
// Button 컴포넌트에서 theme 데이터를 쓰는 경우 - props로 넘겨주기
// App.js
class App extends React.Component {
render() {
return <Toolbar theme="dark" />;
}
}
// Toolbar.js
// 중간 컴포넌트가 데이터를 넘겨줘야 한다.
function Toolbar(props) {
return (
<div>
<ThemedButton theme={props.theme} />
</div>
);
}
// Button.js
class ThemedButton extends React.Component {
render() {
return <Button theme={this.props.theme} />;
}
}
// context api를 사용하여 Button 컴포넌트에서 전역상태 사용하기
const ThemeContext = React.createContext('light');
// App.js
class App extends React.Component {
render() {
// Provider를 이용해 하위 트리에 테마 값을 보내줍니다.
// 아무리 깊숙히 있어도, 모든 컴포넌트가 이 값을 읽을 수 있습니다.
// 아래 예시에서는 dark를 현재 선택된 테마 값으로 보내고 있습니다.
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
}
// Toolbar.js
// 중간 컴포넌트가 일일이 테마를 넘겨줄 필요가 없다.
function Toolbar() {
return (
<div>
<ThemedButton />
</div>
);
}
// Button.js
class ThemedButton extends React.Component {
// 현재 선택된 테마 값을 읽기 위해 contextType을 지정합니다.
// React는 가장 가까이 있는 테마 Provider를 찾아 그 값을 사용할 것입니다.
// 이 예시에서 현재 선택된 테마는 dark입니다.
static contextType = ThemeContext;
function onThemeChange() {
dispatch({
type: 'COLOR_CHANGE',
payload: ,'white'
})
}
render() {
return <Button theme={this.context} onClick = {this.onThemeChange} />;
}
}
컴포넌트가 다시 렌더링할지 여부를 결정할 때 참조를 확인하기 때문에, provider의 부모가 렌더링 될 때마다 불필요하게 하위 컴포넌트가 다시 렌더링 되는 문제가 생길 수도 있다! 예를 들어 아래 코드는 value가 바뀔 때마다 매번 새로운 객체가 생성되므로 Provider가 렌더링 될 때마다 그 하위에서 구독하고 있는 컴포넌트 모두가 다시 렌더링 될 것이다.
class App extends React.Component {
render() {
return (
<MyContext.Provider value={{something: 'something'}}>
<Toolbar />
</MyContext.Provider>
);
}
}
이를 피하기 위해서는 값을 부모의 state로 끌어올려야한다.
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
value: {something: 'something'},
};
}
render() {
return (
<Provider value={this.state.value}>
<Toolbar />
</Provider>
);
}
}
참고 - https://ko.reactjs.org/docs/context.html#gatsby-focus-wrapper