function App() {
return <Children1 value="Hello World" />;
}
function Children1({value}) {
return <Children2 value={ value } />;
}
function Children2({value}) {
return <Children3 value={ value } />;
}
function Children3({value}) {
return <Children4 value={ value } />;
}
function Children4({value}) {
return <p>{ value }</p>;
}
깊숙히 위치한 컴포넌트에 데이터를 전달 할 때 props를 여러개의 컴포넌트를 거쳐 전달해야한다. 이렇게 되면 value가 어디서부터 오는건지 상위 컴포넌트로 타고 타고 올라가야하고 상위 컴포넌트에서 데이터를 추가하여 내려준다거나 value를 data로 바꾼다면 여러 컴포넌트를 수정해야하는 번거로움이 발생한다. 각 컴포넌트에 더 다양한 props가 들어있고 더 까다로운 구조라면 가독성도 떨어질 수 있다. 이러한 문제들을 context로 해결 할 수 있다.
React context는 component 트리의 깊이에 관계없이 props를 전달하지 않고도 component에 데이터를 제공한다. context는 전역데이터를 관리하는데 사용되며 모든 수준에서 수동으로 props를 전달하지 않고도 구성요소 트리를 통해 데이터를 전달 할 수있는 방법을 제공한다.
import { createContext } from "react"
const UserContext = createContext()
위와 같이 createContext 메서드를 사용하여 context 객체를 만들면 react가 이 context 객체를 구독하는 구성요소를 렌더링할때 트리에서 그 위에 가장 근접하게 일치하는 Provider에서 현재 컨텍스트 값을 읽는다. context는 provider가 위치해있는 부모 컴포넌트에서도 사용 할 수 있고 자녀컴포넌트도 사용 할 수 있기 때문에 가장 근접하게 일치하는 provider에서 context값을 읽는 것이다.
// userContext.js
import { createContext } from "react"
const UserContext = createContext()
export function UserProvider(){
const userProfile = {
id: 100,
name: "홍길동",
email: "@gmail.com",
}
return (
<UserContext.Provider value={{ user: userProfile, type: "A" }}>
{children} // <App />
</UserContext.Provider>
)
}
.
.
// main.jsx
import React from "react"
import ReactDOM from "react-dom/client"
import App from "./App.jsx"
import "./index.css"
import { UserProvider } from "./userContext.jsx"
ReactDOM.createRoot(document.getElementById("root")).render(
<React.StrictMode>
<UserProvider>
<App />
</UserProvider>
</React.StrictMode>
)
createContext 메서드에서 provider를 리턴하고 리턴된 값은 생성된 context 객체에 할당된다. UserProvider()는 Context value를 공유받기 원하는 자식컴포넌트에 데이터를 전달할 부모 컴포넌트가 된다.
UserProvider로 감싸진 App컴포넌트는 UserContext.Provider의 자식(children) 컴포넌트로 위치된다.
모든 context객체에는 consumer component가 컨텍스트 변경사항을 구독 할 수 있도록 하는
Provider 구성요소가 함께 제공된다.
<UserContext.Provider value={}>
<AComponent />
<BComponent />
</UserContext>
A.B component 모두 다 context를 구독중이어서 context value에 변경사항이 생기면 컴포넌트를 다시 렌더링한다. 변경사항은 object.is()
와 동일한 알고리즘을 사용하여 새 값과 이전 값을 비교하여 결정된다.
Provider 사용으로 context의 value를 변경해 줄 수 있으며 value props는 provider가 위치해있는 컴포넌트에서 명시해주어야 한다.
object.is(+0, -0) // false
+0 === -0 // true
const { userData } = useContext(UserContext)
.
.
return (
<p>반갑습니다. { userData.name }님</p>
)
context객체(createContext에서 반환된 값)를 인수로 가지고 현재 context value를 반환한다.
현재 context value는 트리에서 호출 구성요소 위에 가장 가까운 <UserContext.Provider>
의 value prop에 의해 결정된다.
component위의 가장 가까운 <UserContext.Provider>
가 업데이트되면 이 Hook은 해당
UserContext Provider에게 전달된 최신 context value로 다시 렌더링의 트리거가 된다.