React - Context API

sarang_daddy·2023년 5월 20일
0

React

목록 보기
5/26
post-thumbnail

리액트로 Issue Tracker를 만드는 과정에서 최상위 컴포넌트의 상태 변경을 위해 하단의 여러 컴포넌트까지 props를 전달해야하는 번거로움이 발생했다.

  • 필터 기능이 포함된 여러 컴포넌트에서 상태를 변경 할 때마다 이슈 목록이 재렌더링 되어야 한다.

  • common 컴포넌트를 제외하고 생각해도 이슈 페이지의 상태를 변경하기 위해 전달되어야 하는 props의 단계가 깊어지고 복잡해 지고 있다.
  • 이처럼 상위 컴포넌트에서 하위 컴포넌트로 데이터를 전달하는 과정에서 여러 개의 중간 컴포넌트를 거치는 경우를 props drilling이라 한다.

props drilling

React는 컴포넌트가 트리 형태의 구조로 상위 컴포넌트에서 하위 컴포넌트로 데이터를 전달한다. 그러나 컴포넌트 계층 구조가 깊어질수록 주안 컴포넌트를 거쳐 데이터를 전달하는 과정이 반복되면서 코드의 가독성과 유지보수성이 저하 될 수 있다. 이런 상황을 props drilling이라 한다.

props drilling을 해결하는 방법

Context API

: React에서 제공하는 Context API를 사용하면 중간 컴포넌트를 거치지 않고도 데이터를 전역적으로 공유할 수 있다.

Redux

: Redux는 React의 상태 관리 라이브러리로, 전역 상태를 관리하기 위해 사용된다. Redux를 사용하면 상태를 중앙 저장소에 저장하고, 컴포넌트 간에 데이터를 전달할 수 있다.

React Query

: React Query는 데이터를 가져오고 관리하기 위한 라이브러리로, 서버에서 데이터를 가져와 컴포넌트에 제공한다. React Query를 사용하면 중간 컴포넌트를 거치지 않고도 데이터를 직접 가져올 수 있다.

Higher-order components (HOC)

: HOC는 컴포넌트를 래핑하여 props를 전달하거나, 컴포넌트를 조작하고 확장하기 위한 패턴이다. HOC를 사용하면 중간 컴포넌트를 거치지 않고도 props를 전달할 수 있다.

Render Props

: Render Props는 컴포넌트의 속성으로 함수를 전달하여 해당 함수를 호출하는 방식이다. 이를 통해 중간 컴포넌트를 거치지 않고도 데이터를 전달할 수 있다.

useContext + Context API

위 방법들 중 React가 제공해주는 Context API를 사용해보자.

Context에서의 글로벌 State 사용 3단계

1. React.CreateContext로 Context 프로바이더 작성

// context.js
import { createContext } from 'react';

export const filterContext = createContext();

2. 작성한 Context의 Provider로 글로벌 state를 사용할 컴포넌트를 감싼다.

// 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>
  );
};

3. 글로벌 state를 참조할 컴포넌트에서 React.useContext 사용

// 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 객체 하나의 값이 변경되면 useContext로 Context를 참조하는 컴포넌트는 모두 재렌더링 된다.
  • 같은 Context에 들어 있는 값이 변경된 경우에는 그 Context를 참조하는 컴포넌트는 모두 변경된다.

하나의 Context에 속성이 다른 다양한 State 함께 두는 것은 피해야 한다.

참고자료

모던 자바스크립트로 배우는 리액트 입문
[별코딩 - React Hooks에 취한다]

profile
한 발자국, 한 걸음 느리더라도 하루하루 발전하는 삶을 살자.

0개의 댓글