15.1 Context API를 사용한 전역 상태 관리 흐름 이해하기
- Context API는 리액트 프로젝트에서 전역적으로 사용할 데이터가 있을 때 유용한 기능
ex) 로그인 정보, 애플리케이션 환경 설정, 테마 etc
- 기존에는 최상위 컴포넌트에서 여러 컴포넌트를 거쳐 props로 원하는 상태와 함수를 전달했지만, Context API를 사용하면 Context를 만들어 단 한번에 원하는 값을 받아와서 사용 할 수 있음
15.2 Context API 사용법 익히기
15.2.1 새 Context 만들기
- 새 Context를 만들 때는 createContext 함수를 사용
- 파라미터에는 해당 Context의 기본 상태를 지정
Context/color.js
import { createContext } from "react";
const ColorContext = createContext({ color:'black'});
export default ColorContext;
15.2.2 Consumer 사용하기
- ColorBox 컴포넌트를 만들어서 ColorContext 안에 들어 있는 색상을 보여줌
- ColorContext 안에 들어 있는 Consumer 컴포넌트를 통해 색상 조회
Components/ColorBox.js
import ColorContext from "../Context/color";
const ColorBox = () => {
return (
<ColorContext.Consumer>
{value => (
<div
style={{
width:'64px',
height:'64px',
background: value.color
}}
/>
)}
</ColorContext.Consumer>
)
}
export default ColorBox;
- Consumer 사이에 중괄호를 열어서 그 안에 함수를 넣어 줌 => Function as a child (Render Props)
- 컴포넌트의 children이 있어야 할 자리에 일반 JSX 혹은 문자열이 아닌 함수를 전달
15.2.3 Provider
- Provider를 사용하면 Context의 value를 변경할 수 있음
- Provider를 사용할 때는 value 값을 명시해 주어야 제대로 작동
App.js
import ColorBox from "./Components/ColorBox";
import ColorContext from "./Context/color";
function App() {
return (
<ColorContext.Provider value={{color:'red'}}>
<div>
<ColorBox />
</div>
</ColorContext.Provider>
);
}
export default App;
15.3 동적 Context 사용하기
15.3.1 Context 파일 수정하기
- Context의 value 값에 함수 전달 가능
Context/color.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}, //상태
action: {setColor, setSubcolor} //업데이트
};
return (
<ColorContext.Provider value={value}>{children}</ColorContext.Provider>
);
};
//const ColorConsumer = Color.Context.Consumer와 같은 의미
const {Consumer: ColorConsumer} = ColorContext;
//ColorProvider와 ColorConsumer 내보내기
export {ColorProvider, ColorConsumer};
export default ColorContext;
- ColorProvider 컴포넌트에서는 ColorContext.Provider를 렌더링
- Provider의 value에는 상태는 state로, 업데이트 함수는 actions로 묶어서 전달
15.3.2 새로워진 Context를 프로젝트에 반영하기
App.js
- ColorContext.Provider를 ColorProvider로 대체
import ColorBox from "./Components/ColorBox";
import { ColorProvider } from "./Context/color";
function App() {
return (
<ColorProvider>
<div>
<ColorBox />
</div>
</ColorProvider>
);
}
export default App;
components/ColorBox.js
- ColorContext.Consumer를 ColorConsumer로 변경
import { ColorConsumer } from "../Context/color";
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;
15.3.3 색상 선택 컴포넌트 만들기
components / SelectColors.js
- Context의 actions에 넣어 준 함수를 호출하는 컴포넌트
const colors = ['red','orange','yellow','green','blue','indigo','violet'];
const SelectColors = () => {
return (
<div>
<h2>색상을 선택하세요.</h2>
<div style={{display:'flex'}}>
{colors.map(color => (
<div
key={color}
style={{
background: color,
width:'24px',
height:'24px',
cursor: 'pointer'
}}
/>
))}
</div>
</div>
)
}
export default SelectColors;
App.js
import ColorBox from "./Components/ColorBox";
import { ColorProvider } from "./Context/color";
import SelectColors from "./Components/SelectColors";
function App() {
return (
<ColorProvider>
<div>
<SelectColors />
<ColorBox />
</div>
</ColorProvider>
);
}
export default App;
- 해당 SelectColors에 마우스 왼쪽 버튼을 클릭하면 큰 정사각형의 색상을 변경하고, 마우스 오른쪽 버튼을 클릭하면 작은 정사각형의 색상을 변경하도록 구현
components/SelectColors.js
import { ColorConsumer } from "../Context/color";
const colors = ['red','orange','yellow','green','blue','indigo','violet'];
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;
15.4 Consumer 대신 Hook 또는 static ContextType 사용하기
- Context에 있는 값을 사용할 때 Consumer 대신 다른 방식을 사용해서 값을 받아오는 방법
15.4.1 useContext Hook 사용하기
- 리액트에 내장되어 있는 useContext Hook 사용
components /ColorBox.js
import { useContext } from "react";
import ColorContext from "../Context/color";
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;
'react' 카테고리의 다른 글
[리액트를 다루는 기술] 17장 리덕스를 사용하여 리액트 애플리케이션 상태 관리하기 (0) | 2023.11.24 |
---|---|
[리액트를 다루는 기술] 16장 리덕스 라이브러리 이해하기 (0) | 2023.11.22 |
[리액트를 다루는 기술] 14장 외부 API를 연동하여 뉴스 뷰어 만들기 (1) | 2023.11.17 |
[리액트를 다루는 기술] 13장 리액트 라우터로 SPA 개발하기 (1) | 2023.11.17 |
[리액트를 다루는 기술] 12장 immer를 사용하여 더 쉽게 불변성 유지하기 (0) | 2023.11.16 |