Amada Coding Club

[React Hook Context API] 리액트 Hook 총정리(6) - useContext (Context API) 본문

Front-End/React

[React Hook Context API] 리액트 Hook 총정리(6) - useContext (Context API)

아마다회장 2023. 2. 2. 12:26

2023.01.28 - [Front-End/React] - [React Hook] 리액트 Hook 총정리(5) - useMemo useCallback (React.memo)

 

[React Hook] 리액트 Hook 총정리(5) - useMemo useCallback (React.memo)

2023.01.28 - [Front-End/React] - [React Hook] 리액트 Hook 총정리(4) - Hook 사용 규칙, Hook 제작방법 [React Hook] 리액트 Hook 총정리(4) - Hook 사용 규칙, Hook 제작방법 [React Hook] 리액트 Hook 총정리(3) - useEffect 2023.01.

amadaclub.tistory.com

오늘 다룰 내용은 useContext이다. 

 

일단 Context에 대해 알아보자. Context란 무엇일까?


Context?

 

context를 이용하면 단계마다 일일이 props를 넘겨주지 않고도 컴포넌트 트리 전체에 데이터를 제공할 수 있습니다.

리액트 공식 홈페이지에 나온 context에 대한 설명이다.

쉽게 생각하면 react에서 사용하는 전역변수! 라고 생각하면 편하다.

 

만약 context가 없을 때를 생각해보자

<C1> -> <C2> -> <C3> -> <C4>

위와 같은 계층 구조에서 c1의 값을 c4로 넘기고 싶을 때 아래와 같이 props를 전달해야 한다

<C1 > -> <C2 props> -> <C3 props> -> <C4 props>

즉 C1에서 C4로 어떤 props를 전달해야 할 때 C2나 C3는 그 props를 사용하지 않음에도 전달해야한다 

 

이 방법 이외에도 props를 보내지 않고 C1에서 C4의 컴포넌트를 props로 보내는 방법도 있다.

function Page(props) {
  const user = props.user;
  const userLink = (
    <Link href={user.permalink}>
      <Avatar user={user} size={props.avatarSize} />
    </Link>
  );
  return <PageLayout userLink={userLink} />;
}

// 이제 이렇게 쓸 수 있습니다.
<Page user={user} avatarSize={avatarSize} />
// ... 그 아래에 ...
<PageLayout userLink={...} />
// ... 그 아래에 ...
<NavigationBar userLink={...} />
// ... 그 아래에 ...
{props.userLink}

위 코드는 공식 홈페이지의  Page 컴포넌트에서 Avatar 컴포넌트의 props를 보내는 방식을 Avatar 컴포넌트를 보내는 방식으로 나타낸 것이다.

 

이러한 방식을 제어의 역전(inversion of control)이라 한다. 

 

이 방법을 사용하게 되면 보내야하는 props가 줄어들고 최상위 컴포넌트가 더 많은 부분을 제어할 수 있기 때문에 더 깔끔한 코드를 만들 수 있다 (제어력이 흩어지면 코드가 난잡해지기 마련 - 중앙집권이 최고 )

 

그러나 로직이 복잡한 경우에는 상위 컴포넌트에 올리게 된다면 그 로직이 더 난해질 수 있고 그 값을 props로 받는 하위 컴포넌트도 더 유연한 처리 과정으로 만들어야 한다. 

 

또한, 하나의 컴포넌트가 아닌 여러 컴포넌트에 값을 전달해야 하는 경우 로직이 더 복잡해질 수 있다. 

 

이러한 문제를 해결하고 값이 변경될 때 하위 컴포넌트들에 값이 변경되었다는 것을 알리고 사용할 수 있도록 돕는 것이 context이다. 그리고 context를 사용할 때 사용하는 API를 Context API라 한다. 


Context 사용법(함수형 컴포넌트)

우선 Context 객체를 만들어야한다.

React.createContext(default값)를 이용해서 context를 만든다

const MyContext = React.createContext(defaultValue);

Provider

하위 컴포넌트에서 위 context를 사용하기 위해선 Provider로 감싸야한다.

<MyContext.Provider value={/* 어떤 값 */}>
	<하위 컴포넌트 />
</MyContext.Provider>

Provider는 하위 컴포넌트에 context의 변화를 알리는 역할을 하고  value값을 전달한다. 

또한, 하위 컴포넌트는 value값이 변경되면 리렌더링된다. 

(value 값이 변경되었는지 확인하는 알고리즘은 object.is 알고리즘과 동일한 알고리즘이기 때문에 value가 객체일 경우에는 문제가 발생할 수 있다.)

Consumer

consumer는 해당 context의 변화를 구독하는 컴포넌트이다. 즉, context의 값이 변경되는 것을 감지하고 그 값을 받아드린다.

 

컴포넌트 내부는 함수여야 하고 상위에 있는 해당 context의 Provider 중 가장 가까운 컴포넌트의 value값을 매개변수로 보낸다.

 

만약 상위에 Provider가 없다면 context의 default값을 사용한다. 

<MyContext.Consumer>
  {value => /* context 값을 이용한 렌더링 */}
</MyContext.Consumer>

useContext()

함수형 컴포넌트에서 context의 value를 사용하고 싶을 때 사용하는 hook이 useContext이다

즉 Context.Consumer와 기능이 동일하다. 형태는 다음과 같다.

const value = useContext(Context명)

useContext를 사용하는 컴포넌트에서 가장 가까운 Provider의 value가 변경되는 경우 변경된 value값을 반환한다. 

그리고 그 value를 사용하면 된다!

 

뭐.. 어렵지 않네...?

오늘은 여기까지

 

참조

https://ko.reactjs.org/docs/context.html