일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 프리온보딩
- state
- localstorage
- react
- 알고리즘
- react localStorage
- Reducer
- 비트 연산자
- CORS
- v9
- axios
- 자바스크립트
- es6
- firebase
- Component
- 파이어베이스
- 컴포넌트
- 원티드
- Redux
- array
- til
- 브라우저
- JS
- JavaScript
- 프론트엔드
- TypeScript
- Frontend
- 리액트
- 타입스크립트
- 프로그래머스
- Today
- Total
도리쓰에러쓰
[React] 전역 상태 관리하기 - useContext() 본문
1. useContext()란?
보통 부모 Component에서 자식 Component로 props를 통해 데이터를 전달하는데, 그 깊이가 깊어진다면 거쳐가야 하는 Component도 많아진다. 그렇게 된다면 코드를 반복적으로 작성해야 하는 일도 많아지고, 변수명이 바뀌면 거쳐가는 모든 Component에서 변수명을 수정해야 하는 등 비효율적인 문제가 발생한다.
이런 비효율적인 문제를 해결하는데에 Context가 꽤나 유용하다. Context를 사용하면 전역적으로 데이터를 공유하기 때문에 데이터가 필요한 Component에서 바로 사용이 가능하게 된다. React Hook인 useContext()는 Context를 좀 더 편하게 사용할 수 있게하는데, 우선 Context API의 개념에 대해 알아보도록 하자.
2. Context API
1️⃣ createContext()
createContext(initialValue);
- context 객체 생성
- createContext() 함수 호출 시 Provider와 Consumer Component 반환
- initialValue : Provider를 사용하지 않았을 때 적용될 초기값
2️⃣ <Context.Provider>
<Context.Provider>
...
</Context.Provider>
- 생성한 context를 하위 Component에 전달
3️⃣ useContext()
const ctx = useContext(context);
- context의 변화를 감시
- 설정한 상태를 불러올 때 사용
3. useContext()를 사용하지 않고 props로만 데이터 전달하기
우선 useContext()를 사용하지 않고 예제를 작성해보려고 한다.
App.js에 있는 데이터를 Meal Component로 props를 통해 데이터를 전달하려고 한다.
📌 Component 경로 : App → Mart → Food → Meal
1️⃣ App.js
import { useState } from "react";
import Mart from "./components/Mart";
const DUMMY_MEALS = [
{
id: 'm1',
name: 'Sushi',
description: 'Finest fish and veggies',
price: 22.99,
},
{
id: 'm2',
name: 'Schnitzel',
description: 'A german specialty!',
price: 16.5,
},
{
id: 'm3',
name: 'Barbecue Burger',
description: 'American, raw, meaty',
price: 12.99,
}
];
const App = () => {
const [items, setItems] = useState(DUMMY_MEALS);
const addMeal = (newItem) => {
setItems([...items, newItem]);
alert(`Add ${newItem}`);
};
return(
<>
<Mart items={items} addMeal={addMeal} />
</>
);
};
export default App;
2️⃣ Mart.js
import Food from "./Food";
const Mart = props => {
return(
<>
<h1>Mart</h1>
<Food items={props.items} addMeal={props.addMeal} />
</>
);
};
export default Mart;
3️⃣ Food.js
import Meal from "./Meal";
const Food = props => {
return(
<>
<h1>Food Corner</h1>
<Meal items={props.items} addMeal={props.addMeal} />
</>
);
};
export default Food;
4️⃣ Meal.js
const Meal = props => {
const newItem = {
id: 'm4',
name: 'Green Bowl',
description: 'Healthy...and green...',
price: 18.99,
};
return(
<>
<h1>Meal Corner</h1>
{props.items.map(item => {
return (
<div key={item.id}>
<h3>{item.name} : {item.price}</h3>
<p>{item.description}</p>
</div>
);
})}
<button onClick={() => {props.addMeal(newItem)}}>+ Add</button>
</>
);
};
export default Meal;
위 예시는 Meal Component의 버튼을 클릭하면 새로운 아이템이 출력 하는 예시이다. Meal Component에서 데이터를 사용하기 위해 Mart, Food Component를 거쳐가고 있다. Mart, Food Component는 단지 데이터만 전달하고 있는 것이 매우 비효율적이다. 위 예시는 간단한 코드이지만 만약 하위 Component가 수십개라면 데이터 관리가 힘들고 유지보수 또한 어려울 것이다. 이제 전역적으로 데이터를 사용할 수 있는 useContext()를 통해 데이터를 접근해보자.
4. useContext() 사용하기
1️⃣ App.js
import { useState, createContext } from "react";
import Mart from "./components/Mart";
export const AppContext = createContext();
const DUMMY_MEALS = [
{
id: 'm1',
name: 'Sushi',
description: 'Finest fish and veggies',
price: 22.99,
},
{
id: 'm2',
name: 'Schnitzel',
description: 'A german specialty!',
price: 16.5,
},
{
id: 'm3',
name: 'Barbecue Burger',
description: 'American, raw, meaty',
price: 12.99,
}
];
const App = () => {
const [items, setItems] = useState(DUMMY_MEALS);
const addMeal = (newItem) => {
setItems([...items, newItem]);
alert(`Add ${newItem}`);
};
return(
<AppContext.Provider value={{items, addMeal}}>
<Mart />
</AppContext.Provider>
);
};
export default App;
2️⃣ Mart.js
import Food from "./Food";
const Mart = () => {
return(
<>
<h1>Mart</h1>
<Food />
</>
);
};
export default Mart;
3️⃣ Food.js
import Meal from "./Meal";
const Food = () => {
return(
<>
<h1>Food Corner</h1>
<Meal />
</>
);
};
export default Food;
4️⃣ Meal.js
import { useContext } from "react";
import { AppContext } from "../App";
const Meal = () => {
const newItem = {
id: 'm4',
name: 'Green Bowl',
description: 'Healthy...and green...',
price: 18.99,
};
const { items, addMeal } = useContext(AppContext);
return(
<>
<h1>Meal Corner</h1>
{items.map(item => {
return (
<div key={item.id}>
<h3>{item.name} : {item.price}</h3>
<p>{item.description}</p>
</div>
);
})}
<button onClick={() => {addMeal(newItem)}}>+ Add</button>
</>
);
};
export default Meal;
Mart, Food Component를 거치지 않아도 useContext()를 사용하여 App Component에서 Meal Component로 데이터를 전달하였다.
💡 useContext() 사용할 때 주의할 점
Provider에서 제공한 value가 달라지면 useContext()를 사용하고 있는 모든 Component가 리렌더링된다.
그래서 useContext()를 사용할 때 value를 메모이제이션(Memoization) 하는 것에 신경 써야 한다.
📌 메모이제이션(Memoization)이 궁금하다면 아래 사이트를 참고하면 좋을 것 같다 !
'React > React' 카테고리의 다른 글
[React] 라이프사이클(Lifecycle)에 대해 (0) | 2022.07.13 |
---|---|
[React] useCallback()과 useMemo() 사용하기 (0) | 2022.05.01 |
[React] ref를 prop으로 넘기기 - forwardRef() (0) | 2022.04.22 |
[React] Ref 사용하여 DOM 요소에 접근하기 - useRef() (0) | 2022.04.21 |
[React] 제어 컴포넌트(Controlled Component)와 비제어 컴포넌트(Uncontrolled Component) (1) | 2022.04.08 |