본문 바로가기

프론트엔드/Java Script

JavaScript Sec05_12 컴포넌트 트리에 데이터 공급(Context API)

  • 부모에서 자식으로만 데이터를 전달하는 단방향 데이터 흐름을 지키는 React의 특성 때문에 props drilling이 일어난다.props 이름 바꾸기도 어렵고 코드 작성과 수정에 악영향을 끼친다.

props 이름 바꾸기도 어렵고 코드 작성과 수정에 악영향을 끼친다.
Provider 컴포넌트는 특별한 컴포넌트로, 자신의 자손에 해당하는 모든 컴포넌트들에게 직통으로 데이터를 줄 수 있다. ⇒ props drilling 해결
Provider 컴포넌트의 자식 컴포넌트들로 배치되어, 해당 Provider 컴포넌트가 공급하는 모든 데이터에 접근할 수 있는 컴포넌트들의 영역을 context라고 표현함

Context API

React에서 문맥 관련 코드를 쉽게 작성할 수 있도록 돕는 API


Context 생성

const MyContext = React.createContext(defaultValue);

 

Context Provider를 통한 데이터 공급

<MyContext.Provider value={전역으로 전달하고자 하는 값}>
{/* 이 context안에 위치할 자식 컴포넌트들*/}
<</MyContext.Provider>

예시)

export const DiaryStateContext = React.createContext();

export const DiaryDispatchContext = React.createContext();

 

cf) export default는 한 파일 당 한 번만 할 수 있고 import 시 중괄호 없이import React from ‘react’ 이런 식으로 사용 가능한 반면, default 없는 export는 여러 번 가능하며 import 시 중괄호를 붙여 import {useContext} from ‘react’처럼 사용 가능하다.

return (
    <div className="App">
      <DiaryStateContext.Provider value={data}>
        <DiaryDispatchContext.Provider value={memoDispatches}>
          <DiaryEditor />
          <div>전체 일기 : {data.length}</div>
          <div>기분 좋은 일기 개수 : {goodCount}</div>
          <div>기분 나쁜 일기 개수 : {badCount}</div>
          <div>기분 좋은 일기 비율 : {goodRatio} %</div>
          <DiaryList />
        </DiaryDispatchContext.Provider>
      </DiaryStateContext.Provider>
    </div>
  );
  • Context 생성 후 자동 생성 되는 Provider 컴포넌트를 불러온다.
  • value 값은 전역으로 전달하고자 하는 값을 넣는다.
    • 중복 Context를 사용하는 이유?
      • Provider도 결국 컴포넌트이므로 prop이 바뀌면 재생성 된다. Provider 컴포넌트가 재생성 되면 밑에 있는 컴포넌트가 전부 강제로 재생성 된다. value에 onCreate, onEdit, onRemove를 넣으면 data state가 바뀔 때마다 리렌더링이 일어나게 되어 최적화가 다 풀리게 된다.
    • memoDispatches를 새로 만들어 useMemo로 감싸주어야 data state가 리렌더 되었을 때 onCreate, onRemove, onEdit 함수를 담은 객체가 재생성 되지 않고 동일한 객체가 prop으로 전달되어 DiaryDispatchContext를 구독하는 컴포넌트가 리렌더 되지 않게 된다.
//DiaryList 컴포넌트
const diaryList = useContext(DiaryStateContext);
//DiaryItem 컴포넌트
const { onEdit, onRemove } = useContext(DiaryDispatchContext);
  • useContext를 이용하여 Provider가 제공해준 값을 불러온다.
  • 인자에는 Context 이름을 넣는다.

context에 관해서 질문드립니다. - 인프런 (inflearn.com)

 💡 정리하자면 Context.Provider에 제공하는 value Props가 바뀌면 이 하위의 컴포넌트들은 모두 리렌더 된다. 이것을 막고 싶다면 리렌더를 방지하고 싶은 컴포넌트에 React.memo를 적용하면 된다. 그러나 함수, 객체 등을 value Props로 전달할 경우 Context에 데이터를 공급하는 컴포넌트가 리렌더 되면 함수나 객체도 다시 생성되기 때문에 리렌더 방지가 효과적으로 이루어지지 않는다. 이를 useMemo를 이용해 해결할 수 있다.