컴포넌트 간에 state를 공유할 수 있게 해주는 Context를 배우다.
1. Context ?
리액트는 상위 컴포넌트에서 하위 컴포넌트로 데이터가 이동하는 단방향 전달 방식(그림 1)이다. 우리가 지금까지 실습했을 때는 컴포넌트의 계층구조가 단순했다. 많아야 3층이었는데, 실제로 프로젝트를 진행하게 되면 컴포넌트의 구조가 복잡해지고 계층이 많아지는 현상이 생길 수밖에 없다. 여태 배운 개념만으로는 예를 들어 5층에 있는 컴포넌트에 최상위 컴포넌트의 state를 전달하기 위해서는 하위 컴포넌트에 props로 하나하나 전달해주는 방법밖에 없다. 이런 현상을 Prop Drilling이라고 한다. 그리고 state의 이름을 변경하면 또 하나 하나 props의 이름을 바꿔줘야 하는 번거로움이 있기 때문에 Context를 사용해야 한다.
(그림 3) Context는 App안에서 전역적으로 사용되는 데이터들을 여러 컴포넌트끼리 쉽게 공유할 수 있도록 지원하는 기술이다. 하위 컴포넌트에서 "나 그 state 사용하고 싶어요"라고 하면 필요한 컴포넌트에서 useContext를 사용해서 Context에 저장되어 있는 것들을 사용할 수 있는 것이다. Context를 사용하면 Prop Drilling 현상도 일어나지 않는다. 그냥 원하는 컴포넌트에서 바로 사용하면 되기 때문이다.
그렇다면 Context로 특정 컴포넌트에서 state를 자유롭게 사용할 수 있는데 왜 props를 사용하는 것일까? "props 안 쓰고 그냥 다 Context에 저장해서 쓰면 편할 텐데.."라는 날로 먹으려는 생각은 접어두자. Context는 꼭 필요할 때만 사용해야 한다.
- Context를 사용하면 컴포넌트를 재사용하기 어려워질 수 있다.
- Prop Drilling을 피하기 위한 목적이라면 Component Composition (컴포넌트 합성)을 먼저 고려한다.
2. Context 사용법
Context를 사용하기 위해서 src 폴더 내부에 context 폴더를 새롭게 만든다. 파일의 첫 번째 스펠링은 무조건 대문자로 시작한다. context 파일내부에서 context를 만들고 export로 내보내서 다른 파일에서 불러와서 사용하는 방식이다.
// CounterContext.jsx (Context 정의)
import { createContext } from "react";
// 전역으로 state를 관리하기 위한 context 생성
export const CounterContext = createContext(null)
import로 createContext를 불러와서 context를 만들고 임의의 변수에 넣고 내보낸다. 그리고 context를 사용할 최상위 컴포넌트에서 불러온다.
// App.js (상위 컴포넌트)
import { useState } from 'react';
// import './App.css';
import Counter from "./components/Counter"
import { CounterContext } from './context/CounterContext';
function App() {
const [count, setCount] = useState(0)
return (
<CounterContext.Provider value={{count, setCount}}>
<Counter />
</CounterContext.Provider>
)
}
export default App;
import로 context 폴더 내부의 파일을 불러온다. import 다음의 { } 중괄호 안에 있는 건 사용자 마음대로 이 이름으로 사용하겠다는 것이다. 하지만 편하게 파일 이름과 동일하게 하는 게 좋다. 이름을 붙였으니 그 이름으로 return안의 태그들을 모두 감싸는 태그를 만들어준다. 위 코드에선 <CounterContext.Provider>이다. Context를 제공한다는 의미의 태그이다. 우리가 props로 전달했던 것과 비슷하게 value에 속성값을 객체형태로 Context에 담는다.
// Counter.jsx (하위 컴포넌트)
import React, { useContext } from 'react'
import { CounterContext } from '../context/CounterContext'
const Counter = () => {
const {count, setCount} = useContext(CounterContext)
return (
<div>
<h1>{count}</h1>
<button onClick={() => setCount(count + 1)}>증가</button>
</div>
)
}
export default Counter
Context를 사용할 하위 컴포넌트에서 import로 react안의 useContext를 불러온다. (자동완성이 안될 경우)
현재 Context에는 count와 setCount인 state와 state함수가 들어있다. 가져온 count와 setCount 함수를 해당 컴포넌트에서 적절하게 사용하기만하면 된다. 너무 쉽고 편한 Context, 맛만 보자!
- src > context 폴더를 생성하고 Context 컴포넌트 파일을 생성한다. ex) OOOContext.jsx
- 최상위 컴포넌트에서 import로 Context를 불러온다.
- <OOOContext.porvider value={{state, setState}}> 컴포넌트로 <App/>을 감싸준다.
- 하위 컴포넌트에서는 useContext()를 이용하여 state와 setState를 가져온다.
'Front-End > React.js' 카테고리의 다른 글
[React.js] react-router (useParams, useSearchParams) (2) | 2023.09.12 |
---|---|
[React.js] Life Cycle / useEffect (0) | 2023.09.05 |
[React.js] useRef 설명 및 실습 (0) | 2023.08.30 |
[React.js] Filter 함수 (0) | 2023.08.29 |
[React.js] map 함수 / 컴포넌트 응용 (0) | 2023.08.28 |