기존 컴포넌트간에 상태를 교류해야할 때 무조건 부모 -> 자식 흐름으로 props를 통해 전달하였는데, 이제는 ContextAPI를 통해 더 쉽게 상태를 교류할 수 있다. 프로젝트 컴포넌트 구조가 간단하고 다루는 상태 종류가 많지 않다면 Context를 사용할 필요는 없지만 전역적으로 사용되는 상태가 있고 컴포넌트 개수가 많은 상황에서 유용하게 사용할 수 있다.
아래에서 App-H-J , App-A-B-F, App-A-B-E-G 로 접근하던 것을 바로 접근할 수 있다.
Consumer
우선 프로젝트를 새로 생성한다.
yarn create react-app context-tutorial
다음 파일들을 생성한다.
- src/contexts/color.js
import {createContext} from 'react';
const ColorContext = createContext({color : 'black'});
export default ColorContext;
여기에서 생성하는 ColorContext를 소비자를 통해 color에 접근할 수 있다.
- src/components/ColorBox.js
import ColorContext from '../contexts/colors';
const ColorBox = () => {
return(
<ColorContext.Consumer>
{value => (
<div
style = {{
width: '64px',
height: '64px',
background: value.color
}}
/>
)}
</ColorContext.Consumer>
);
};
export default ColorBox;
위에서 만든 ColorContext.Consumer에서 위에서 생성한 객체를 value로 받아 value.color로 접근할 수 있다.
-app.js
import ColorBox from './components/colorBox.js';
const App = () =>{
return(
<div>
<ColorBox />
</div>
)
}
export default App;
실행하면 다음과 같이 나타난다.
Provider
provider를 사용하면 Context의 value를 변경할 수 있다.
import ColorBox from './components/colorBox';
import ColorContext from './contexts/colors';
const App = () =>{
return(
<ColorContext.Provider value={{color:'red'}}>
<div>
<ColorBox />
</div>
</ColorContext.Provider>
)
}
export default App;
Provider를 사용할 때는 value를 명시하지 않으면 에러가 난다!!
위의 내용이 고정적인 값들만 사용한 경우라면, 업데이트를 하는 경우도 있다.
함수를 넣을 수 있는데 다음과 같이 변경해볼 수 있다.
- contexts/colors.js
import {createContext, useState} from 'react';
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;
ColorProvider에서 ColorContext.Provider를 렌더링하면서 Provider의 value에 상태(state)와 업데이트함수(actions)를 묶어서 전달하고 있다.
- components/ColorBox.js
import {ColorConsumer} from '../contexts/colors';
const ColorBox = () => {
return(
<ColorConsumer>
{value => (
<>
<div
style = {{
width: '64px',
height: '64px',
background: value.state.color
}}
/>
<div
style = {{
width: '32px',
height: '32px',
background: value.state.subColor
}}
/>
</>
)}
</ColorConsumer>
);
};
export default ColorBox;
- App.js
import ColorBox from './components/colorBox';
import {ColorProvider} from './contexts/colors';
const App = () =>{
return(
<ColorProvider>
<div>
<ColorBox />
</div>
</ColorProvider>
)
}
export default App;
현재까지는 정한 값을 보여주는데, Context의 actions에 있는 함수를 호출하는 컴포넌트를 만들 수 있다.
- components/SelectColors.js
import {ColorConsumer} from '../contexts/colors';
const colors = ['red', 'orange', 'yellow', 'green', 'blue']
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
import ColorBox from './components/colorBox';
import {ColorProvider} from './contexts/colors';
import SelectColors from './components/selectColors';
const App = () =>{
return(
<ColorProvider>
<div>
<SelectColors />
<ColorBox />
</div>
</ColorProvider>
)
}
export default App;
색을 선택하면 색이 변경된다!
이를 좀 더 간결하게 사용하기 위해 useContext Hook을 사용할 수도 있다.
-components/ColorBox.js
import {useContext} from 'react';
import ColorContext from '../contexts/colors';
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;
'Programming > React.js' 카테고리의 다른 글
14. Redux로 React app 상태 관리 (0) | 2022.10.26 |
---|---|
13. Redux (0) | 2022.09.17 |
11. 라우터로 SPA 개발하기 (0) | 2022.09.08 |
10. immer사용하여 불변성 유지하기 (0) | 2022.08.31 |
9. 컴포넌트 성능 최적화 (0) | 2022.08.24 |