Web-Frontend/React.js

[React.js] Context 사용하여 데이터 전달하기

서노리 2023. 1. 21. 17:33
반응형

Context 사용하는 경우

위는 현재 진행하고 있는 일기장 프로젝트의 컴포넌트 트리 구조이다. 최말단 컴포넌트인 DiaryItem에 prop을 전달하기 위해서는 최상단 컴포넌트인 App에서 중간 단계 컴포넌트인 DiaryList에 prop을 넘겨주고 이를 다시 DiaryItem에 전달하는 방식을 따르게 되는데 이는 너무 번거롭고 규모가 커질 수록 복잡해질 것이다. 이러한 경우 Context를 사용하여 단계마다 일일이 props를 넘겨주지 않고도 컴포넌트 트리 전체에 데이터를 제공할 수 있다.

 

Context

Context는 리액트 컴포넌트 트리 안에서 전역 데이터를 공유하고 관리할 수 있는 방법이다.

 

<Context 생성하기>

react 패키지에서 제공하는 createContext 함수를 사용하여 Context를 생성한다.

Context는 전역 데이터를 담고있는 하나의 저장 공간이라고 생각할 수 있다.

다음과 같이 createContext 함수의 인자로 해당 컨텍스트에 저장할 값을 넘긴다.

그리고 외부 컴포넌트에서 이를 사용하기 위해서 export를 통해 내보내는 작업이 필요하다.

import { createContext } from "react";

export const DiaryStateContext = createContext(null);

 

<Context 저장하기>

다음과 같이 어떤 컴포넌트를 Context의 Provider로 감싸주면, 그 하위에 있는 모든 컴포넌트들은 해당 컨텍스트에 저장되어 있는 전역 데이터에 접근할 수 있게 된다.

return (
    <DiaryStateContext.Provider value={data}>
        <div className="App">
          <DiaryEditor />
          <DiaryList />
        </div>
    </DiaryStateContext.Provider>
  );

 

<Context에 접근하기>

React Hooks 중 useContext를 이용하면 컨텍스트에 저장된 전역 데이터에 접근할 수 있다.

const { data } = useContext(DiaryStateContext);

※ 중첩된 Context 사용해야 하는 경우

하위 컴포넌트에 다양한 함수 또한 전달해주기 위해 다음과 같은 코드를 작성하면 문제가 발생한다.

return (
    <DiaryStateContext.Provider value={data, onCreate, onEdit, onRemove}>
        <div className="App">
          <DiaryEditor />
          <DiaryList />
        </div>
    </DiaryStateContext.Provider>
  );

Provider도 결국 컴포넌트이기 때문에 prop이 변경될 경우 재생성되어 그 하위 컴포넌트들도 재생성되게 된다. 즉, data와 함께 함수들도 같이 전달하게 되면 data가 변경될 때마다 리렌더링 되어 그동안의 최적화들이 모두 의미없게 된다.

이러한 경우 중첩 Context를 사용하여 문제를 해결할 수 있다.

 

 export const DiaryDispatchContext = createContext(null);
 
 const memoizedDispatch = useMemo(() => {
    return { onCreate, onRemove, onEdit };
  }, []);

return (
    <DiaryStateContext.Provider value={data}>
      <DiaryDispatchContext.Provider value={memoizedDispatch}>
        <div className="App">
          <DiaryEditor />
          <DiaryList />
        </div>
      </DiaryDispatchContext.Provider>
    </DiaryStateContext.Provider>
  );

상태 변화 함수들을 전달할 새로운 컨텍스트를 생성한 뒤 상태 변화 함수들을 useMemo로 묶어서 Provider에 전달하여, 중첩된 컨텍스트를 사용하여 문제를 해결한 모습이다.


 

반응형