일반적으로 부모와 자식간 props를 날려 state를 변화시켰던 react 방식과는 달리
context api는 컴포넌트 간 간격이 없다.
즉, 컴포넌트를 건너띄고 다른 컴포넌트에서 state, function을 사용할 수 있다.
context는 컴포넌트 안에서 전역적으로 데이터를 공유하도록 나온 개념이다.
그런 데이터는 로그인 데이터, 웹 내 사용자가 쓰는 설정파일, 테마, 언어 등등 다양하게 컴포넌트 간 공유되어야할 데이터로 사용하는 것이 좋다.
React.createContext
const MyStore = React.createContext(defaultValue);
provider
로 부터 context를 정의한 변수 myStore
를 감싸면 된다.defaultValue
는 트리안에 적절한 provider를 찾지 못했을 때 쓰이는 값이다.Context.Provider
<MyStore.Provider value={this.state}>
<subComponent1 />
<subComponent2 />
</MyStore.Provider>
provider
는 정의한 context를 하위 컴포넌트에게 전달하는 역할value
를 사용해야 한다.Context.Consumer
<MyContext.Consumer>
{value => /* context 값을 이용한 렌더링 */}
</MyContext.Consumer>
createContext()
에서 정의한 defaultValue
를 가진다.createContext
// src/store.js
import React from "react";
const Store = React.createContext(null);
export default Store;
// src/rootStore.js
import React from "react";
const rootStore = React.createContext({ zxc: "testsetst" });
export default rootStore;
provider
// src/App.jsx
import React, { Component } from "react";
import Test from "components/Test";
import Test3 from "components/Test3";
import Test2 from "components/Test2";
import Store from "store";
export default class App extends Component {
constructor(props) {
super(props);
this.changeMessage = () => {
const { message } = this.state;
if (message === "hello") {
this.setState({
message: "by"
});
} else {
this.setState({
message: "hello"
});
}
};
this.state = {
test: "testContext",
message: "hello",
changeContext: this.changeMessage
};
}
render() {
const { test } = this.state;
return (
<Store.Provider value={this.state}>
<Test test={test} />
<Test2 />
<Test3 />
</Store.Provider>
);
}
}
consumer
// src/components/Test.jsx
import React, { Component } from "react";
import PropTypes from "prop-types";
import Store from "store";
export default class Test extends Component {
render() {
const { test } = this.props;
return (
<div>
<Store.Consumer>{store => store.message}</Store.Consumer>
<Store.Consumer>
{store => (
<button type="button" onClick={store.changeContext}>
changeContext
</button>
)}
</Store.Consumer>
{test}
</div>
);
}
}
Test.propTypes = {
test: PropTypes.string
};
Test.defaultProps = {
test: ""
};
2개의 store
// src/components/Test2.jsx
import React, { Component } from "react";
import rootStore from "rootStore";
import Store from "store";
export default class Test2 extends Component {
static contextType = rootStore;
componentDidMount() {
// rootStore context 구독
console.log(this.context);
}
render() {
return (
<>
{/* store context 구독 */}
<Store.Consumer>{store => store.message}</Store.Consumer>
<div>test2 </div>
</>
);
}
}
provider가 네스팅되어 상위 provider 값도 받아야 할때
// src/components/Test3.jsx
import React, { Component } from 'react';
import Store from 'store';
import rootStore from 'rootStore';
// import PropTypes from 'prop-types';
class TT extends Component {
static contextType = rootStore;
componentDidMount() {
const { value } = this.props;
console.log('ttt', value);
console.log('root', this.context);
}
render() {
const { value } = this.props;
return <div>test3{value.message}</div>;
}
}
const Test3 = () => <Store.Consumer>{store => <TT value={store} />}</Store.Consumer>;
export default Test3;
TT.propTypes = {
value: {},
};
TT.defaultProps = {
value: {},
};