리액트로 Issue Tracker를 만드는 과정에서 최상위 컴포넌트의 상태 변경을 위해 하단의 여러 컴포넌트까지 props를 전달해야하는 번거로움이 발생했다.
props drilling
이라 한다.React는 컴포넌트가 트리 형태의 구조로 상위 컴포넌트에서 하위 컴포넌트로 데이터를 전달한다. 그러나 컴포넌트 계층 구조가 깊어질수록 주안 컴포넌트를 거쳐 데이터를 전달하는 과정이 반복되면서 코드의 가독성과 유지보수성이 저하 될 수 있다. 이런 상황을 props drilling
이라 한다.
: React에서 제공하는 Context API
를 사용하면 중간 컴포넌트를 거치지 않고도 데이터를 전역적
으로 공유할 수 있다.
: Redux
는 React의 상태 관리 라이브러리
로, 전역 상태를 관리하기 위해 사용된다. Redux를 사용하면 상태를 중앙 저장소에 저장하고, 컴포넌트 간에 데이터를 전달할 수 있다.
: React Query
는 데이터를 가져오고 관리하기 위한 라이브러리로, 서버에서 데이터를 가져와 컴포넌트에 제공한다. React Query를 사용하면 중간 컴포넌트를 거치지 않고도 데이터를 직접 가져올 수 있다.
: HOC
는 컴포넌트를 래핑하여 props를 전달하거나, 컴포넌트를 조작하고 확장하기 위한 패턴이다. HOC를 사용하면 중간 컴포넌트를 거치지 않고도 props를 전달할 수 있다.
: Render Props
는 컴포넌트의 속성으로 함수를 전달
하여 해당 함수를 호출하는 방식이다. 이를 통해 중간 컴포넌트를 거치지 않고도 데이터를 전달할 수 있다.
위 방법들 중 React가 제공해주는 Context API를 사용해보자.
// context.js
import { createContext } from 'react';
export const filterContext = createContext();
// issuePage.jsx
import { filterContext } from 'context.js'
export const IssuePage = () => {
// --- //
// 전역으로 사용할 데이터 혹은 상태
const [filters, setFilters] = useState(initialFilter);
// --- //
return (
// 전역으로 사용할 데이터 or 상태를 value로 전달
<filterContext.Provider value={[filters, setFilters]}>
// --- // 글로벌 state를 사용한 컴포넌트들
<Filterbar options={options}></Filterbar>
<Tab buttonDatas={labelAndMilestoneInfo}></Tab>
<IssueList
issueData={issueData}
userList={userList}
milestoneList={milestoneList}
labelList={labelList}
issueCount={issueCount}
></IssueList>
// --- // 감싸준다.
</filterContext.Provider>
);
};
// Filterbar.jsx
// react에서 useContext 가져온다.
import { useContext } from 'react';
// 작성한 Context를 가져온다.
import { filterContext } from 'context.js'
export const Filterbar = ({ options }) => {
// 전달 받은 props가 아님에도 사용이 가능하다.
const [filters, setFilters] = useContext(filterContext);
// IssueListHeader.jsx
import { useContext } from 'react';
import { filterContext } from 'context.js'
export const IssueListHeader = ({
userList,
milestoneList,
issueCount,
labelList,
}) => {
// 전달 받은 props가 아님에도 사용이 가능하다.
const [filters, setFilters] = useContext(filterContext);
// FilterElement.jsx
import { useContext } from 'react';
import { filterContext } from 'context.js'
export const FilterElement = ({
filterName,
filterKey,
options,
selectedOption,
}) => {
// 전달 받은 props가 아님에도 사용이 가능하다.
const [filters, setFilters] = useContext(filterContext);
하나의 Context에 속성이 다른 다양한 State 함께 두는 것은 피해야 한다.