[React] 리액트 컴포넌트간 데이터 전달 : Context 훅에 대한 정리 (feat. createContext + useContext)
Context란?
1. useContext란?
React의 Context란 컴포넌트간의 데이터를 전달하는 방법이다.
props와는 달리 createContext훅과 useContext훅을 이용하여 컴포넌트간 데이터를 전달 할 수 있다.
2. useContext를 왜 사용하는걸까?
그럼 props를 이용해서 컴포넌트간 데이터를 전달하면 되는거 아닌가? 라는 생각이 들 수 있다.
근데 props에는 커다란 문제가 있었는데.. 자기 자식한테만 보낼 수 있다는 문제이다..
뭐 고작 그런거 가지고? 라고 할 수 있는데, 만약 자식컴포넌트가 엄청 많다면? 아래와 같은 문제가 발생한다..
자식의 자식의 자식의 자식까지 계속 props로 전달해야 한다. 즉 한번에 보내지 못한다는 문제..
이런 걸 Props Drilling이라고 한다.. 드릴로 땅을 파서 지하까지 내려가는 것처럼 보이기 때문..
이런 Props Drilling 문제를 해결하기 위해 우리는 오늘 배울 Context를 사용한다.
Context를 사용하는 경우 위 그림과 같이 아무 자식컴포넌트에게나 직접적으로 데이터를 전달 할 수 있다.
이제 Context의 기본적인 사용법과 효율적으로 사용할 수 있는 방법까지 알아보자..
Context 기본문법
createContext 훅을 이용하여 Context 생성
//createContext 훅 import
import { createContext } from "react";
// createContext 훅을 이용하여 Context 컴포넌트 생성
const MyContext = createContext();
// Context에 초기값을 부여할 수도 있음
// const MyContext = createContext({count: 0});
/* 생성한 Context는 컴포넌트이기 때문에 일반적인 컴포넌트를 사용하듯이 사용한다.
단 Provider 프로퍼티를 이용해야함.. <컴포넌트명.Provider>과 같이 작성하고
데이터를 전달 할 컴포넌트들을 감싸면 해당 컴포넌트에 걸쳐있는 모든 컴포넌트들에
데이터를 전할 할 수 있다. */
<MyContext.Provider value={{ count: 0 }}>
<Child />
</MyContext.Provider>
useContext 훅을 이용하여 Context 사용
//useContext 훅을 import
import { useContext } from "react";
//createContext훅으로 생성 된 Context import
import { MyContext } from "../App.jsx";
//useContext 함수에 Context명을 파라메터로 넣어 Context 데이터를 사용
const { childData, setChildData } = useContext(MyContext);
대충 내용을 요약하자면
1. createContext훅을 이용하여 Context 컴포넌트 생성.
2. 데이터를 전달하고자 하는 컴포넌트를 <컴포넌트명.Provider data={}>와 같은 형식으로 감싸준다.
3. 데이터를 받고자 하는 컴포넌트에서 useContext훅을 이용하여 데이터를 받는다.
과 같은 로직을 통하여 데이터를 전달한다... 샘플코드를 보면 더 이해하기 쉬울 거 같다..
Context 샘플코드
App.jsx
import { useState } from "react";
import { Child1 } from "./todo/Child1.jsx";
import { createContext } from "react";
//Context 컴포넌트 생성 및 export
export const MyContext = createContext();
const App = () => {
//테스트를 위한 state 생성
const [childData, setChildData] = useState([
{ id: 1, data: "Child1 데이터입니다." },
{ id: 2, data: "Child2 데이터입니다." },
]);
return (
<>
<div className="App">
//Context컴포넌트의 Provider 프로퍼티로 자식컴포넌트(Child1)를 감쌈
//data는 sate와 setState를 보냄
<MyContext.Provider value={{ childData, setChildData }}>
<Child1 />
</MyContext.Provider>
</div>
</>
);
};
export default App;
Child1.jsx
import { useContext } from "react";
import { MyContext } from "../App.jsx";
import { Child2 } from "./Child2.jsx";
export const Child1 = () => {
//App.jsx에서 받은 state를 사용하기 위해 useContext훅으로 값을 받음
const { childData, setChildData } = useContext(MyContext);
return (
<>
//state값 사용
{childData.find((child) => child.id == 1).data} <br></br>
//자식 컴포넌트 Child2
<Child2 />
</>
);
};
Child2.jsx
import { useContext } from "react";
import { MyContext } from "../App.jsx";
export const Child2 = () => {
//App.jsx에서 state를 받기 위해 useContext 훅을 사용
const { childData, setChildData } = useContext(MyContext);
//App.jsx에서 받은 데이터를 사용
return <>{childData.find((child) => child.id == 2).data}</>;
};
결과
대충 위 샘플코드의 로직을 그림으로 표현하면 아래와 같다..
기존의 props를 사용했다면 App.jsx에서 Child1.jsx로 먼저 데이터를 보내고, Child1.jsx에서 Child2.jsx로
데이터를 보내야 했겠지만, Context를 이용함으로써 App.jsx에서 바로 Child2.jsx까지 데이터를 전달 할 수 있게 되었다.
글이 길어져서 다음에 Context를 모듈로 분리하는 방법과 모듈로 분리하는 이유에 대해 정리해봐야겠다..