✅ 기본 개념
- 리액트 App은 컴포넌트 간에 데이터를 props로 전달
- 이는 데이터를 주고받는 구조가 복잡해지면 유지보수성이 낮아지는 등 단점 발생
- 이를 더욱 편하게 하는 전역 상태 관리 작업을 가능하게 해줌
- 보통 Redux나 MobX 같은 상태 관리 라이브러리 많이 사용하지만,
- 리액트 v16.3 업데이트 이후 Context API가 많이 개선되어 쉽게 사용 가능
✅ Context 사용해보기
🔸 createContext - Context 만들기
- createContext 함수를 사용해 새 Context를 만들고 기본 상태 지정
import {createContext} from 'react';
const SampleContext = createContext({ greet : 'Hi' })
export default SampleContext;
🔸 Consumer
- 값을 props로 받아오지 않고 생성한 Context 안에 있는 Consumer로 값 조회
import SampleContext from '../contexts/sampleContext';
const SampleComponent = () => {
return (
<SampleContext.Consumer>
{
value => (
<div>{value.greet}</div>
)
}
</SampleContext.Consumer>
)
}
🔸 Provider
- Provider를 사용해 Context의 value를 변경할 수 있음
// App.js에서
import SampleComponent from '';
import SampleContext from '';
const App = () => {
return(
<SampleContext.Provider value = {{greet : 'hello'}}>
<div>
<SampleComponent/>
</div>
</SampleContext.Provider>
)
}
- createContext에서 넣어준 기본값은 Provider를 사용하지 않았을 때만 사용됨
=> Provider는 사용했는데 value 넣지 않으면, 기본값도 사용하지 않으므로 오류 발생
✅ 여러 값 관리하는 동적 Context
🔸 Context 수정해보쟈
- Context의 value에는 상태 값 뿐만 아니라 함수 전달도 가능
import {createContext, useState} from 'react';
const SampleContext = createContext({
state : { greet : 'Hi', name : 'Yu' },
actions : {
setGreet : () => {},
setName : () => {}
}
})
const SampleProvider = ({children}) => {
const [greet, setGreet] = useState('Hi');
const [name, setName] = useState('Yu');
const value = {
state : { greet, name },
actions : { setGreet, setName}
};
return (
<SampleContext.Provider value = {value}> {children} </SampleContext.Provider>
)
};
// const SampleConsumer = SampleContext.Consumer와 같은 의미
const { Consumer : SampleConsumer } = SampleContext;
export { SampleProvider, SampleConsumer }
export default SampleContext;
- Provider의 value에서 상태는 state, 업데이트 함수는 actions로 묶어 전달
- 반드시 묶어줄 필요는 없으나, state, actions를 분리해두면 다른 컴포넌트에서 Context 값 사용 시 편리
- createContext의 기본값은 실제 Provider의 value에 넣는 객체의 형태와 일치시켜주는 게 좋음
🔸 여러 값 Context 사용해보기
- App.js에서 SampleContext.Provider => SampleProvider로 변경
import SampleComponent from '';
import {SampleProvider} from '';
const App = () => {
return(
<SampleProvider>
<div>
<SampleComponent/>
</div>
</SampleProvider>
)
}
import {SampleConsumer} from '../contexts/sampleContext';
const SampleComponent = () => {
return (
<SampleConsumer>
{
value => (
<>
<div>{value.state.greet}</div>
<div>{value.state.name}</div>
</>
)
}
</SampleConsumer>
/* 이렇게도 가능
<SampleConsumer>
{
({state}) => (
<>
<div>{state.greet}</div>
<div>{state.name}</div>
</>
)
}
</SampleConsumer>
*/
)
}
🔸 동적 Context 사용해보기
// 새로 생성한 SelectName.js
import {SampleConsumer} from '';
const names = ['Kim','Lee','Park','Ma','Jung'];
const SelectName = () => {
return (
<div>
<SampleConsumer>
{({actions}) => (
<div style={{display : 'flex'}}>
{
names.map( name => (
<div key = {name} onClick = {() => actions.setName(name)}>
{name}
</div>
))
}
</div>
)}
</SampleConsumer>
</div>
)
}
// App.js
...
const App = () => {
return(
<SampleProvider>
<div>
<SelectName/>
<SampleComponent/>
</div>
</SampleProvider>
)
}
✅ useContext Hook 사용하기
- 함수형 컴포넌트에서는 Consumer 대신 useContext Hook을 사용할 수 있음
- SampleComponent에서
import SampleContext from '';
import { useContext } from 'react';
const SampleComponent = () => {
const {state} = useContext(SampleContext);
return (
<div>
<div>{state.greet}</div>
<div>{state.name}</div>
</div>
)
}