지금까지 일기앱의 컴포넌트간 data 흐름을 도식화하면 위와 같습니다. 크게 4가지 컴포넌트로 이루어졌는데 이때 DiaryList
컴포넌트에 대해서 잠깐 설명드리고자 합니다.
DiaryList
컴포넌트는 App 컴포넌트에서 useReducer
로 받아온 data
를 리스트 형태로 반환만 해주는 역할을 수행합니다.
그리고 data간 수정,삭제는 한 컴포넌트에서 이루어질 수 없기 때문에 DiaryItem
에 상태변화 함수를 props로 전달하는 작업 flow 였습니다.
이렇게 DiaryList
에서는 특정 props가 쓰이지 않고 전달용으로만 소비되는 행위를 Props Drilling이라고 합니다.
useContext()
로 방지하기그럼 위와 같이 만약 App
컴포넌트 하위에 Provider
로 각각의 컴포넌트에 맞는 props를 전달을 하면 어떨까요? 그렇게 된다면 Props Drilling을 방지할 수 있습니다.
useContext()
사용법우선 App 컴포넌트 밖에다가 context를 정의해줘야 합니다.
export const DiaryStateContext = React.createContext();
이때 데이터를 Provider를 통해 전달을 하고 그리고 그 전달받은 value를 하위 컴포넌트들이 받기 때문에 export
명령어로 Context
를 명시합니다.
return(
<DiaryStateContext.Provider value = {data}>
{/*이 Context 내에 위치할 자식 컴포넌트들*/}
</DiaryStateContext.Provider>
);
아까 상단에서 설명한 DiaryList
를 예시로 코드를 리팩토링을 해봅시다.
아래는 기존 DiaryList
의 코드입니다.
const DiaryList = ({diaryList}) => {
return (
<div className="DiaryList">
<h2>일기 리스트</h2>
<h4>{diaryList.length}개의 일기가 있습니다.</h4>
</div>
);
}
App 컴포넌트에서 Provider를 export 했기 때문에 이를 이제 import 후, diaryList
Props는 더이상 필요없기 때문에 위의 코드에서 삭제합니다.
import { useContext } from "react";
import DiaryItem from "./DiaryItem";
import { DiaryStateContext } from "./App";
const DiaryList = () => {
const diaryList = useContext(DiaryStateContext);
return (
<div className="DiaryList">
<h2>일기 리스트</h2>
<h4>{diaryList.length}개의 일기가 있습니다.</h4>
</div>
);
}
useContext()
로 App 컴포넌트에 선언된 Provider로 현재 value값을 전달받을 수 있습니다.
또한 리액트 개발자 도구로 해당 컴포넌트간 계층구조가 어떻게 이루어졌는지 살펴볼 수 있습니다.
다음 포스팅에선 App컴포넌트에서 선언된 상태관리 함수들을 useContext()
로 관리하는 방법에 대해서 다뤄보도록 하겠습니다.