Adhithi Ravichandram 의 글을 번역하고, 중간 중간 필요한 내용을 추가하여 작성한 글입니다. 많은 의역이 들어갔으므로 원문 Learn the useContext Hook in React를 읽어보시는 것을 추천드립니다.
위 글 외에는 기본적으로 React 공식 문서를 참고하여 작성하였고, 추가적으로 인용하거나 참고한 글은 해당 글 아래에 출처를 명시하였습니다.
만약 당신이 리액트 개발자라면, 그리고 리액트 훅에 대해서 아직 한 번도 안 들어봤다면 지금이 딱! 배우기 좋은 시기다. 이 글에서는 useContext 훅에 대해서 배울 것이다. 이전 글에서 다른 훅에 대해서 다뤘는데 이 글을 시작하기 전에 그 글들을 먼저 보는 걸 추천한다.
노트: 만약 리액트를 처음 접한다면, 훅을 먼저 배우고 나서 추가로 필요하다고 느낄 때 기존의 방식대로 학습하는 걸 추천한다.
훅(Hooks)이란 리액트 state 및 lifecycle(생명 주기) 기능을 건져(hook) 낼 수 있는 기능입니다. 훅은 클래스 안에서 일하지 않고, 클래스 없이 리액트를 사용할 수 있다. - 리액트 공식 블로그
자, 이제 useContext 훅의 세계로 빠져보자!
기존의 React 애플리케이션에서 데이터는 위에서 아래로(부모에서 자식으로), props를 통해 전달 된다. 이는 컴포넌트 구조가 복잡해지고, 깊이가 깊어질수록 너무 많은 컴포넌트를 거쳐야 한다는 문제를 야기한다.
이를 해결 하기 위해서 전역 상태 관리 라이브러리인 redux를 도입하기도 하는데, 지난 글에서 말했든 전역에서 사용되는 데이터를 위해 꼭 redux를 써야만 하는 것은 아니다. React에서 제공하는 context를 사용하면 일일이 props로 넘겨주지 않아도 컴포넌트 트리 전체에서 데이터를 사용할 수 있다.
즉, context는 props를 통하지 않아도, 꼭 위에서 아래로 흘러 흘러 전달해 주지 않아도, 어느 컴포넌트에서든 전역 데이터에 접근할 수 있게 해준다.
지난 글에서 예시를 들었던 언어나 테마 설정 등 애플리케이션 전역에서 적용 되는, 그래서 전역에서 접근 해서 확인해야하는 데이터를 공유하는데에 쓰이는 방법이 context이다.
그리고 이를 활용하게 하는 훅이 useContext 훅이다.
Context API에는 다음과 같은 것들이 있다.
바로 위에서 말했듯이 context는 핵심은 props로 일일이 내려주지 않고 여러 컴포넌트에 데이터를 전달하는 것이다. 이에 context를 사용하게 되면 컴포넌트 재사용이 어려워지므로, 이 때에는 컴포넌트 합성이 더 나을 수도 있다.
우선, 이 글은 useContext에 대한 글이니, context에 대한 예시를 더 살펴보도록 하자.
첫 번째 단계는 useContext 훅을 불러 들이는 것이다.
import React, { useContext } from "react";
아래에 보이듯이, blogInfo라는 변수에 state를 저장해 보겠다. 이는 데이터를 저장하기 위한 아주 단순한 store이다.
const blogInfo = {
React: {
post: "Learn useContext Hooks",
author: "Adhithi Ravichandran"
},
GraphQL: {
post: "Learn GraphQL Mutations",
author: "Adhithi Ravichandran"
}
};
이 데이터는 우리의 store이다. 애플리케이션에 필요한 만큼 이런 스토어를 많이 만들 수 있다.
blogInfo를 전달하는 context를 만들어보자.
const blogInfoContext = React.createContext(blogInfo);
우리는 방금 막 blogInfoContext를 만들었다. 다음 단계는 이 context를 사용해서 props 없이도 컴포넌트가 이 데이터(blogInfo)를 쓰도록 하는 것이다.
어떤 컴포넌트가 context를 필요로 하느냐에 따라 다르지만, 우리는 Context.Provider를 사용해서 해당 컴포넌트들에게 context 를 제공할 수 있다. React는 그 컴포넌트가 컴포넌트 트리 어디에 있는지 전혀 신경 쓰지 않는다.
예제 안에서, 나는 부모 컴포넌트를 만들고, BlogDetailComponent와 MyOtherBlogInfoComponent라는 두 개의 자식 컴포넌트를 Provider와 context 값으로 감쌌다.
function ParentComponent() {
return (
<blogInfoContext.Provider value={blogInfo}>
<h2>Use Context Example Component</h2>
<BlogDetailComponent />
<MyOtherBlogInfoComponent />
</blogInfoContext.Provider>
}
다시 말하자면, 부모 컴포넌트를 만들고 두 개의 자식 컴포넌트를 context 값을 가진 Provider로 감쌌다.
이전 단계에서까지, 우리는 아직 hook을 사용하지 않았다. context가 컴포넌트에 제공되고 나면, 우리는 함수 컴포넌트 없이도 hook을 사용할 수 있게 된다.
useContext의 문법은 다음과 같다.
const value = useContext(MyContext);
만약 이전에 훅 없이 context를 사용해 본 적이 있다면, 아마 당신은 Consumer가 익숙할 것이다. useContext(MyContext) 는 클래스 컴포넌트의 <MyContext.Consumer> 와 유사하다.
하지만, useContext(MyContext.Provider) 또는 userContext(MyContext.Consumer) 를 사용하지 마라.
useContext 훅은 context 그 자체만 파라미터로 받는다.
우리의 함수 컴포넌트 안에서 useContext 훅을 사용해보자. 첫 번째 컴포넌트에서, React blog post에 대한 정보를 보여주기 위해서 blogInfoContext 를 사용해보자.
function BlogDetailComponent() {
const blogDetails = useContext(blogInfoContext);
return (
<div>
<h3>React Blog Details</h3>
<p>Topic: {blogDetails.React.post}</p>
<p>Author: {blogDeails.React.author}</p>
</div>
);
}
useContext를 사용한 컴포넌트는 주어진 context 값이 바뀔 때마다 항상! 다시 렌더링 된다. 즉, 컴포넌트 내에서 context가 유효하다면, state의 변화에 대해 신경 쓸 필요가 전혀 없다는 뜻이다.
두 번째 컴포넌트에서는 blogInfoContext를 사용해 GraphQL blog post에 대한 정보를 보여주자.
function MyOtherBlogInfoComponent() {
const blogDetails = useContext(blogInfoContext);
return (
<div>
<h3>GraphQL Blog Details</h3>
<p>Topic: {blogDetails.GraphQL.post}</p>
<p>Author: {blogDetails.GraphQL.author}</p>
</div>
);
}
아래 code-sandbox를 통해 위의 예제 코드를 다 합쳤을 때 어떻게 동작하는지 보자.
https://codesandbox.io/s/reacts-hooks-examples-zqmzm
이 포스트는 https://programmingwithmosh.com/에 최초로 업로드 된 글이다.
훅은 React에 새롭게 도입된 컨셉으로, React 공식 문서에는 모든 컴포넌트를 훅을 사용해서 새롭게 쓰는 건 추천하지 않는다고 나와있다. 대신, 새로운 컴포넌트를 사용할 때는 훅을 사용하는 것을 추천한다.
참고로, 이 글은 2020년에 쓰여진 글입니다. 지금은 다들, hook 잘 알죠...?
만약 이 글에 나오는 예제를 사용해서 이것 저것 해보고 싶다면, 내 깃허브 레포지토리를 참고하길 바란다:
useContext 훅 외에도 다른 훅이 있으니, 이는 다른 글에서 또 다뤄보도록 하겠다.