- Hook은 React 버전 16.8부터 React 요소로 새로 추가되었습니다. Hook을 이용하여 기존 Class 바탕의 코드를 작성할 필요 없이 상태 값과 여러 React의 기능을 사용할 수 있습니다.
- 출처: Hook의 개요 - React 공식 문서
Hook은, 아주아주아주x100 짧게 말하자면 Class
를 사용하지 않고도 State, 생명주기 메서드(LifeCycle Method)와 같은 React 기능을 함수형 컴포넌트에서도 사용할 수 있도록 해준다.
React에는 기본적으로 제공하는 내장 훅(Built-in Hooks)이 있는데,
이번 글에서는 React 내장 훅 중 하나인 useContext
에 대해 공부하고자 한다🤓
- context를 이용하면 단계마다 일일이 props를 넘겨주지 않고도 컴포넌트 트리 전체에 데이터를 제공할 수 있습니다.
- context는 React 컴포넌트 트리 안에서 전역적(global)이라고 볼 수 있는 데이터를 공유할 수 있도록 고안된 방법입니다.
- context의 주된 용도는 다양한 레벨에 네스팅된 많은 컴포넌트에게 데이터를 전달하는 것입니다.
- 출처: Context - React 공식 문서
React로 개발을 하다보면, 상위 컴포넌트로부터 하위 컴포넌트에게 데이터를 전달해야하거나,
컴포넌트 트리 내에서 데이터를 전역적(global)
으로 관리를 할 상황이 자주 일어난다.
이때 컴포넌트 트리 구조가 복잡하거나 거대한 경우에는,
단순히 데이터를 넘겨주기 위한 용도의 컴포넌트가 생성되기도 한다.
예를 들면, X라는 데이터를 D 컴포넌트에서 사용한다고 가정하자.
A→B→C→D
X가 엄청난 환승을 거쳐야한다. 아주 힘든 여정이다.
데이터만 잘 넘겨졌으면 된거 아니야?🤨라고 생각할 수 있는데,
우리의 환승을 생각해보자.
저 멀리 목적지에 가기 위해 버스 탔다가 지하철로 환승. 지하철에서 또 버스로 환승...
굉장히 귀찮고 피곤하지 않은가😖
그리고 장기적으로 봤을 때 컴포넌트 트리 구조가 굉장히 복잡해지기 때문에
컴포넌트를 관리하는 것이 어려워지게 된다.
이 쯤에서 다시 한 번 「useContext의 'Context'란 무엇일까?🤔」 소제목 밑의
React 공식 문서페이지로부터 인용된 설명을 보자.
context를 이용하면, 일일이 props를 넘겨주지 않고도 컴포넌트 트리 전체에서 데이터를 사용할 수 있습니다🤭
느낌이 오는가?
나는 Context
를 보물 상자💎📦 라고 이해했다. (혹시 비유가 잘못됐다면 지적해주세요!)
소중한 녀석들을 한 곳에 모아두고 저장하는 보물 상자.
Context
는 우리의 소중한 데이터를 담아두고 저장하는 보물 상자💎📦 인 것이다.
소중한 데이터를 저장해두는 보물 상자💎📦 = Context
를 마련해둠으로써,
상위 컴포넌트에서 하위 컴포넌트로 하나하나 데이터를 건네주지 않아도
소중한 데이터를 언제든지 꺼내볼 수 있도록 했기 때문에,
언제 어디서든 보물 상자 a.k.a. Context
에 접근해서 필요한 데이터를 꺼내볼 수 있다.
↑ Context와 기존의 props를 넘겨주는 방식을 그림으로 표현하자면 요런 느낌.
Context
에 데이터를 담아두었기 때문에 원하는 계층에서 바로 그 데이터를 가져와서 사용할 수 있다.
즉, 컴포넌트 트리 전체에서 언제 어디서나 전역적(global)
으로 데이터를 사용할 수 있게 해주는 것이 Context
이다.
이렇게 유용한 Context
로부터 데이터를 가져와서 사용하기 위하여
React 내장 훅으로 구현된 것이 바로바로 오늘의 주인공인 useContext
이다🥰
유저 이름을 표시하는 아주아주아주x100 간단한 웹 페이지를 만들어 보자.
아래의 결과 화면에서 John
은 Context
에 저장된 값을 불러온 것이다.
Context
를 생성할 때에는 createContext
라는 함수를 사용한다.
createContext
의 파라미터에는 해당 Context
에 기본값으로 설정할 값을 입력한다.
기본값을 따로 지정하지 않을 경우에는 파라미터를 비워두거나 null
을 입력.
// context.js
import React from "react";
export const UserNameContext = React.createContext(null);
또는
// context.js
import React, { createContext } from "react";
export const UserNameContext = createContext(null);
위 두가지 방법 모두 Context를 생성한다는 결과는 같다.
createContext
를 언제 불러오느냐의 차이.
아래의 캡쳐와 같이 1️⃣ 에서 생성했던 UserNameContext
를 console.log
해보면,
Context
내부에는 Provider
라는 컴포넌트가 있다는 것을 알 수 있다.
이 Provider
란 무엇일까?
- Provider 컴포넌트는 value prop을 받아서 이 값을 하위에 있는 컴포넌트에게 전달합니다.
- 출처: Context - React 공식 문서
// App.js
import React from "react";
import Screen from "./Screen";
import { UserNameContext } from "./context";
export default function App() {
return (
<UserNameContext.Provider value="John">
<Screen />
</UserNameContext.Provider>
);
}
Context
의 값은 Provider
컴포넌트를 통해 설정할 수 있다.
위의 공식 문서의 설명과 같이, Provider
컴포넌트는 value
라는 prop
을 받게 되는데,
Context
의 값을 설정할 때는 이 Provider
컴포넌트의 value prop
에 값을 설정해준다.
value prop
에 설정하는 값은 바로, 실제로 하위 컴포넌트에 전달하려는 값이다.
앞서 「useContext의 'Context'란 무엇일까?🤔」 파트에서 예시로 설명했던 아래의 내용에서,
예를 들면, X라는 데이터를 D 컴포넌트에서 사용한다고 가정하자.
A→B→C→D
X가 엄청난 환승을 거쳐야한다. 아주 힘든 여정이다.
여기서 X
라는 데이터가 Provider
컴포넌트의 value prop
의 값이 된다.
이Provider
컴포넌트로 감싸진 모든 컴포넌트는 Context
에 대한 접근권한이 생기게 되는데,
Provider
컴포넌트로 감싸진 컴포넌트 내에서는 어디서든지 Context
의 값을 조회해서 사용할 수 있게 된다.
위의 예시 코드에서 Screen
컴포넌트는 Provider
컴포넌트로 감싸져 있기 때문에, Context
의 값을 조회해서 사용할 수 있게 된다.
2️⃣ 의 예시 코드에서 등장한 Screen
컴포넌트는
Provider
컴포넌트로 감싸져 있기 때문에 Context
에 접근을 할 수 있게 됐다.
자, 그럼 Screen
컴포넌트에서 Context에 저장된 값을 사용하기 위해서는 어떻게 해야 할까?
그렇다! 여기서 바로 우리의 주인공인 useContext
가 등장하게 된다!!👏
useContext
를 사용함으로써 Context의 값=Provider 컴포넌트에서 지정했었던 value값
을 사용할 수 있게 된다!
// Screen.js
import React, { useContext } from "react";
import { UserNameContext } from "./context";
export default function Screen() {
const userName = useContext(UserNameContext);
return <p>My name is {userName}</p>;
}
useContext
를 사용하기 위해, React로부터 useContext
라는 Hook을 import
한다. (앞서 언급했듯이 useContext
는 React의 내장 Hook임. 그렇기 때문에 React로부터 import가 가능함)context.js
에서 생성했던 UserNameContext
라는 이름의 Context
를 import
한다.UserNameContext
라는 Context
에 담긴 값을 사용하고 불러오기 위해 useContext
를 사용. useContext
의 인자에는 2행에서 불러온 Context
인 UserNameContext
를 지정한다. userName
이라는 정수를 만들어서 그 안에 UserNameContext
의 값을 넣는다.userName
을 사용한다.이렇게 Context
에 저장된 값인 John
을 불러와서 출력하는 것에 성공👏
Context
와 useContext
를 통해 같은 데이터를 여러 컴포넌트가 공유할 때 발생하는 문제와
데이터를 하위 컴포넌트로 전달할 때 발생되는 문제를 해결함으로써,
컴포넌트 트리를 복잡한 컴포넌트 구성에서 벗어날 수 있다는 것을 알았다.
아주아주아주x100000 간단한 예시여서 useContext
의 진가를 보여주지 못했지만...
useContext
를 useState
와 같은 또다른 Hook들과 조합해서 쓰는 등
얼마든지 응용을 한다면 좀 더 유용하게 사용할 수 있을거라는 생각이 든다.
혹여나 이 페이지에 틀린 정보가 있다면 마구마구 지적해주시면 감사하겠습니다!🙇♀️