📢 어렵고 정석적인 개념 설명보다는 저같은 초보자도 이해하기 쉽게 정리하는 것을 원칙으로 포스팅하고 있습니다. 😄

[React] Context API를 이용하여 전역으로 값 관리하기

What

App.js - List.js - Item.js의 순서대로 자식 컴포넌트가 있다고 가정해보자. 즉, App.js가 최상위 부모 컴포넌트고 그 밑으로는 List.js, 또 그 밑으로는 Item.js 컴포넌트가 있는 것이다. 만약, App 컴포넌트의 state를 Item 컴포넌트에게 전달하려면 어떻게 해야할까? 기존의 일반적인 방법으로는 App이 List 컴포넌트에게 props를 먼저 전달하고, 전달받은 props를 다시 Item 컴포넌트로 전달하는 과정을 거쳐야 했다. List 컴포넌트는 해당 props를 쓰지도 않는데 그저 Item 컴포넌트의 부모 컴포넌트라는 이유로 props를 전달하는 다리 역할만 한 것이다.

 

이것은 매우 비효율적이다. 지금은 3개의 컴포넌트지만, 10개라면? 생각만 해도 이보다 더 귀찮을 수가 없다. 리액트에서는 이것을 더 효율적으로 처리하기 위해 Context API를 제공한다. 기존의 굽이굽이 거쳐가는 방식이 아닌 데이터들을 모아두는 공급소(Context) 역할을 만들어서 어떤 컴포넌트든 바로 원하는 데이터를 얻을 수 있게 되었다.

 

How

기존의 컴포넌트 props 전달 방식

/* App.js */

const App = () => {
    const [data, setData] = useState("Hello!")
    return <div>
        <List data={data} />
    </div>
}

export default App;
/* List.js */

const List = ({ data }) => {
    return <div>
        <Item data={data} />
    </div>
}
/* Item.js */

const Item = ({ data }) => {
    return <div>
        <p>{data}</p>
    </div>
}

export default Item;

App 컴포넌트의 state를 Item 컴포넌트에게로 전달하고자 한다. 이를 위해 List 컴포넌트는 그저 중간 다리 역할을 수행해야만 했다. 

 

Context API 이용

/* App.js */

export const finalData = React.createContext(); // Context를 만들어준다.

const App = () => {
    const [data, setData] = useState("Hello!");
    return (
    <finalData.Provider value={data}>
            <div>
                <List />
            </div>
        </finalData.Provider>
    ) 
}

export default App;
/* List.js */

const List = () => {
    return <div>
        <Item />
    </div>
}
/* Item.js */

import { useContext } from 'react';
import { finalData } from './App';

const Item = () => {
    const data = useContext(finalData); // finalData의 value 값 가져오기
    return <div>
        <p>{data}</p>
    </div>
}

export default Item;

중간 다리를 거치지 않고, Context를 통해 데이터를 가져올 수 있게 되니까 컴포넌트가 훨씬 깔끔해졌다.

Context 영역의 value 값을 가져오기 위해서는 useContext 함수가 필요하다. 또한, Context를 import 해와야 한다.

 

정리하자면, 데이터를 뿌리는 쪽(주로 최상위 컴포넌트)은 Context 영역을 만들어야 하고, 데이터를 받아오는 쪽은 만들어진 Context 영역을 import하면서 useContext를 통해 value 값을 가져오면 된다.

 

/* useContext 비구조화 할당 */

// App.js
const hanlder = {onCreate, onEdit, onRemove};
return <dataContext.Provider value={handler}> // 이하 생략

// Editor.js
import { dataContext } from './App';
const handler = useContext(dataContext);
const {onCreate} = handler;

만약, Context의 value가 여러 개라면 비구조화 할당을 통해 변수를 보내주고 받으면 된다.

참고로, 비구조화 할당으로 된 value 값을 받을 때는 { }로 감싸서 변수 선언해줘야 한다는 것을 잊지 말자.

 

1. export const 영역이름 = React.createContext(); // Context 영역 만들기
2. <영역이름.Provider value={뿌릴 값}>으로 전체를 감싸주기
3. import {영역이름} from './영역위치'
4. const 값 이름 = useContext(영역이름) // value 값 받아오기
// 1~2번은 데이터를 뿌리는 부모 컴포넌트, 3~4번은 데이터를 받는 자식 컴포넌트
5. useContext()를 사용하면 컴포넌트에 props를 따로 전달하지 않아도 된다.