React - useContext

춤추는개발자·2023년 4월 1일
0
post-thumbnail

위와 같이 App 컴포넌트에서 데이터를 컴포넌트에게 전달 해줄려면 prop 으로 하위 컴포넌트를 따라 전달해 줘야 합니다. 이것을 prop drilling 이라고 합니다.

보기만해도 피곤하며 prop 를 엉뚱한 컴포넌트에게 전달하거나 전달해주는것을 깜빡할것만 같습니다. 그리고 굳이 해당 데이터가 필요 없는 컴포넌트가 하위 컴포넌트가 데이터가 필요하다는 이유로 prop 로 데이터를 받아야 합니다. 너무 비효율적 입니다.

우리에게 희망적인 소식이 있습니다.
React 는 App 안에서 전역적으로 사용되는 데이터들을 컴포넌트들끼리 쉽게 공유할 수 있는 방법을 제공합니다. context 에 모든 데이터를 공유하면 데이터가 필요한 컴포넌트가 useContext 를 사용하면 하나하나 prop 를 이용해 컴포넌트에 전달해주지 않아도 하위 컴포넌트가 데이터를 받아 사용 할 수 있습니다.

하지만 Context 를 사용하면 컴포넌트를 재사용하기 어려워 질 수 있기 때문에 필요할때만 사용하고 일반적으로는 prop 를 사용하는게 컴포넌트의 재사용성을 높여 줍니다. Context 의 사용이 prop drilling 을 하지 않기 위한 목적으로 사용한다면 컴포넌트 합성을 사용하는것이 좋은 선택일수도 있습니다.

그럼 이제 useContext 를 사용해봅시다!
최대한 간단하게 설명하기 위해서 App 컴포넌트를 최상위 컴포넌트로 두고 한개의 하위 컴포넌트인 Greet 라는 하위 컴포넌트만 만들어서 설명하도록 하겠습니다.
이 앱은 클릭하기! 버튼을 클릭하면 인사가 바뀌는 앱 입니다.


위의 앱에서는 두개의 컴포넌트가 필요 합니다.

import React, { useState } from 'react';
import Greet from './Greet';

const App = () => {
  const [greet, setGreet] = useState('안녕하세요!');

  return (
    <>
      <Greet greet={greet} setGreet={setGreet} />
    </>
  );
};

export default App;

App 컴포넌트와

import React from 'react';

const Greet = ({ greet, setGreet }) => {
  const onclickGreetButton = () => {
    setGreet(greet === '안녕하세요!' ? '안녕히가세요!' : '안녕하세요!');
  };
  return (
    <>
      <div>
        <h1>{greet}</h1>
        <button onClick={onclickGreetButton}>인사하기!</button>
      </div>
    </>
  );
};

export default Greet;

Greet 컴포넌트 입니다.

App 컴포넌트에서 Greet 컴포넌트에게 prop 로 greet, setGreet 를 전달 합니다.
그리고 prop 로 전달 받은 것을 Greet 컴포넌트에서 사용합니다.

제가 아주아주 간단한 앱을 만들었기 때문에 하나의 하위 컴포넌트에 prop 을 전달했지만 실제 우리가 사용하는 앱들은 아주아주 많은 하위 컴포넌트들이 존재하고 하위 컴포넌트에게 데이터를 전달하기 위해서 prop 을 전달해야 할 것 입니다.


Context , useContext 사용하기

이제 우리는 Context 를 사용해 prop 로 전달했던 데이터를 저장하고 그 데이터를 필요로 하는 컴포넌트가 useContext 로 데이터를 받아 사용하도록 코드를 작성 해 보겠습니다.

import { Context, createContext } from 'react';

export const GreetData = createContext(null);

먼저 새로운 파일 만들어 줍니다. 확장자는 js 또는 jsx 로 설정 합니다.
저는 GreetData 라는 이름의 파일을 만들었고 위와 같은 코드를 작성해 Context 를 생성했습니다.

import React, { useState } from 'react';
import Greet from './Greet';
import { GreetData } from './Greetdata';

const App = () => {
  const [greet, setGreet] = useState('안녕하세요!');

  return (
    <>
      <GreetData.Provider value={{ greet, setGreet }}>
        <Greet />
      </GreetData.Provider>
    </>
  );
};

export default App;

이제 App 컴포넌트 코드에서 위와 같이 변경 해 줍니다.
이전에 prop 를 사용할때와 변경 된 것은 GreetData.provider 라는 사용자 태그로 기존의 Greet 컴포넌트를 감싸주는 것과 Greet 컴포넌트로 이제 prop 를 전달하지 않는다는 것 그리고 prop 를 대신해서 GreetData.provider 사용자 태그에 value 라는 prop 을 받는데 값으로 모든 컴포넌트가 사용할 데이터를 객체 형태로 전달 합니다.
이렇게 하면 하위 컴포넌트가 필요한 데이터가 있다면 useContext 를 사용해서 데이터를 가져와 사용할 수 있습니다.

import React, { useContext } from 'react';
import { GreetData } from './Greetdata';

const Greet = () => {
  const { greet, setGreet } = useContext(GreetData);
  const onclickGreetButton = () => {
    setGreet(greet === '안녕하세요!' ? '안녕히가세요!' : '안녕하세요!');
  };
  return (
    <>
      <div>
        <h1>{greet}</h1>
        <button onClick={onclickGreetButton}>인사하기!</button>
      </div>
    </>
  );
};

export default Greet;

Greet 컴포넌트에서는 greet, setGreet 가 필요하기 때문에 useContext(생성한 context) 로 필요한 데이터를 가져와서 사용 합니다.

위의 작은 앱을 만드는 경우에는 사실 Context, useContext 를 사용하는것보다 그냥 prop 으로 데이터를 전달해주는 것이 효율적일 것 입니다. 하지만 많은 하위 컴포넌트를 가지는 앱에서는 Context, useContext 를 사용하면 효율적으로 데이터를 필요로 하는 하위 컴포넌트에게 데이터를 전달하도록 하여 앱을 만들 수 있을 것 입니다.

0개의 댓글