Dev/JS

[JS] React.js Context API 알아보기

JieunJieun 2018. 6. 3. 15:46

Context


 일반적인 React 어플리케이션에서 데이터들은 prop를 통해 하향식(부모 -> 자식) 으로 전달이 됩니다. 하지만,

어플리케이션 내에 많은 컴포넌트들이 특정 타입의 props(예를 들어 locale 설정, ui 테마) 를 받기 위해서는 좀 번거로울 수 있습니다.

그래서 Context 는 트리 레벨을 통해 prop를 전달하지 않으면서 컴포넌트 끼리 값을 공유하는 방법을 제공합니다.





Context를 언제 사용하느냐?


 Context는 현재 인증된 사용자, 테마, 또는 기본 설정 언어와 같은 React 의 여러 컴포넌트에 대해서 '전역' 으로 

여겨질 수 있는 데이터들을 공유하도록 설계되었습니다.  예를 들어 아래 코드에서는 Button 컴포넌트의 스타일을

지정하기 위해 'Theme' props를 수동으로 전달합니다



class App extends React.Component {
render() {
return <Toolbar theme="dark" />;
}
}


function Toolbar(props) {
// 툴바 컴포넌트는 무조건 "theme" props를 가져야 합니다.
// 그리고 이것을 ThemeButton로 전달해야 합니다.
// 만약, 앱에 있는 모든 single 버튼들이 테마를 가져야 할때는 정말 번거롭겠죠?
// 왜냐! 그것을 하기 위해서는 모든 컴포넌트들을 거쳐야 하기 때문이죠
return (
<div>
<ThemedButton theme={props.theme} />
</div>
);
}


function ThemedButton(props) {
return <Button theme={props.theme} />;
}



컨텍스트를 사용하면, 중간 컴포넌트를 거치지 않고 prop를 전달할 수 있습니다.



// 컨텍스트는 깊숙히 있는 컴포넌트 트리를 통해서 값을 보낼 수 있게 합니다.
// 모든 컴포넌트들을 거치는 번거로운 작업 없이 말이죠.
// 현재 테마를 위한 컨텍스트를 만들어 보겠습니다. ("light" 라는 default 테마를 사용해서요)
const ThemeContext = React.createContext('light');


class App extends React.Component {
render() {
// Provider를 사용하여 현재 테마를 트리 아래에다 전달합니다.
// 다른 컴포넌트들은 테마가 얼마나 깊은곳에 위치했냐 안했냐 몰라도 그냥 읽을 수 있습니다.
// 이 예제에서는, 우리는 "dark" 테마를 현재 값으로 보낼 것 입니다.
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
}


// 중간에 있는 컴포넌트들은 테마를 하향식으로 더이상
// 보내지 않아도 됩니다.
function Toolbar(props) {
return (
<div>
<ThemedButton />
</div>
);
}


function ThemedButton(props) {
// 이제 Consumer를 통해서 현재 테마의 값을 테마 컨텍스트로 읽을 수 있습니다.
// React가 가까운 테마 Provider를 찾아서 그 값을 사용할 수 있게 해줍니다.
// 이 예제 에서의 현재 테마는 "dark" 입니다.
return (
<ThemeContext.Consumer>
{theme => <Button {...props} theme={theme} />}
</ThemeContext.Consumer>
);
}



참고 : props가 많은 단계 아래로 통과되는 것이 아니면 Context 를 사용하지 마세요!




API - React.createContext



const {Provider, Consumer} = React.createContext(defaultValue);


{ Provider, Consumer } 짝을 만듭니다. 그리고 React가 Consumer 컨텍스트를 렌더링하면, Consumer 와 가장 가까운 Provider 위에 

일치하는 컨텍스트 값을 읽어옵니다.


그리고 인수로 넣어준 defaultValue 는 트리에서 일치하는 Provider가 없는 경우에만 Consumer가 사용하게끔 되어있습니다.

이는 컴포넌트를 개별적으로 테스트 할 때 유용합니다. 


참고 : undefined Provider 값을 전달한다고 해서 Consumer가 defaultValue를 사용하는 것은 아닙니다.


API - Provider



<Provider value= { /* some code here */}>


Consumer 가 Context의 변경사항을 가져올 수 있게 하는 React Component 입니다.


value는 Provider가 Consumer에게 전달할 props 가 들어갈 자리입니다. 이때 하나의 Provider는

많은 Consumer들과 연결될 수 있습니다. 또한, Provider를 여러개 중첩하여 트리 내에서 더 깊은 값을 무시할 수 도 있습니다.




API - Consumer



<Consumer>
{value => /* 컨텍스트 값이 렌더링됩니다. */}
</Consumer>


Consumer는 Context의 변경사항을 읽을 수 있는 컴포넌트 입니다.

이때 자식 컴포넌트로서의 기능이 필요합니다. 이 함수는 현재 Context 값을 받고 React 노드를 반환하고 있습니다. 
value 함수에 전달된 인수는 트리에서 이 컨텍스트에 대해서 가장 가까운 Provider의 props와 같습니다. 

위의 컨텍스트에 대한 Provider가 없는 경우, value 인수는 위의 createContext 에서 전달된 defaultValue 와 같습니다.