React의 컨텍스트 API 소개
게시 됨: 2022-03-10이 튜토리얼에서는 후크에 대해 충분히 이해하고 있어야 합니다. 그래도 시작하기 전에 이 문서에서 사용할 후크와 후크에 대해 간략하게 설명하겠습니다.
React 문서에 따르면:
" Hooks 는 React 16.8에 새로 추가된 기능입니다. 클래스를 작성하지 않고도 상태 및 기타 React 기능을 사용할 수 있습니다."
이것이 기본적으로 React hook이 무엇인지입니다. 이를 통해 기능 구성 요소에서 상태, 참조 및 기타 React 기능을 사용할 수 있습니다.
이 기사에서 만나게 될 두 가지 후크에 대해 논의해 보겠습니다.
useState
후크
useState 후크 를 사용하면 기능 구성 요소에서 상태를 사용할 수 있습니다 . useState
후크는 상태의 초기 값을 유일한 인수로 취하고 두 요소의 배열을 반환합니다. 첫 번째 요소는 상태 변수이고 두 번째 요소는 상태 변수의 값을 업데이트하는 데 사용할 수 있는 함수입니다.
다음 예를 살펴보겠습니다.
import React, {useState} from "react"; function SampleComponent(){ const [count, setCount] = useState(0); }
여기서 count
는 상태 변수이고 초기 값은 0
이고 setCount
는 count 값을 업데이트하는 데 사용할 수 있는 함수입니다.
useContext
후크
이 기사의 뒷부분에서 이에 대해 논의하겠지만 이 후크 를 사용하면 기본적으로 컨텍스트 값을 사용할 수 있습니다. 이것이 실제로 의미하는 바는 이 기사의 뒷부분에서 더 분명해질 것입니다.
원사 작업 공간
Yarn 작업 공간을 사용하면 모놀리식 저장소(monorepo)를 사용하여 프로젝트 코드베이스를 구성할 수 있습니다. React는 monorepo이고 Yarn 작업 공간을 사용하여 해당 목적을 달성하는 오픈 소스 프로젝트의 좋은 예입니다. 관련 기사 읽기 →
컨텍스트 API가 필요한 이유는 무엇입니까?
우리는 React 앱의 밝은 모드와 어두운 모드 사이를 토글하는 "테마 토글러" 구성 요소를 만들고 싶습니다. 모든 구성 요소는 현재 테마 모드에 액세스할 수 있어야 적절하게 스타일을 지정할 수 있습니다.
일반적으로 props를 통해 모든 구성 요소에 현재 테마 모드를 제공하고 state
를 사용하여 현재 테마를 업데이트합니다.
import React from "react"; import ReactDOM from "react-dom"; function App() { return ( <div> <Text theme= "blue" /> <h1>{theme}</h1> </div> ); } function Text({theme}) { return( <h1 style = {{ color: `${theme}` }}>{theme}</h1> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);
위의 코드 샘플에서 h1
요소를 렌더링하는 Text Component를 만들었습니다. h1
요소의 색상은 현재 테마 모드에 따라 다릅니다. 현재 테마는 파란색입니다. state
를 사용하여 blue
과 red
테마 사이를 전환할 수 있습니다.
useState
후크를 사용하여 "테마"라는 상태를 만듭니다. useState
후크는 테마의 현재 값과 테마를 업데이트하는 데 사용할 수 있는 함수를 반환합니다.
이제 테마 상태를 생성해 보겠습니다.
const [theme, setTheme] = React.useState("blue");
또한 App
구성 요소에 버튼 요소를 추가합니다. 이 버튼은 테마를 전환하는 데 사용되며 클릭 이벤트 핸들러가 필요합니다. 따라서 다음과 같이 클릭 이벤트 핸들러를 작성해 보겠습니다.
const onClickHandler = () => { setTheme(); }
이제 현재 테마가 Blue
이면 새 테마를 Red
로 설정하고 그 반대의 경우도 마찬가지입니다. if
문을 사용하는 대신 JavaScript에서 삼항 연산자를 사용하는 것이 더 편리한 방법입니다.
setTheme( theme === "red"? "blue": "red");
이제 onClick
핸들러를 작성했습니다. 이 버튼 요소를 App
구성 요소에 추가해 보겠습니다.
<button onClick = {onClickHandler}>Change theme</button>
Text 컴포넌트의 theme props 값을 theme state로 변경해 보겠습니다.
<Text theme={theme}/>
이제 다음이 필요합니다.
import React from "react"; import ReactDOM from "react-dom"; import "./styles.css"; function App() { const[theme, setTheme] = React.useState("red"); const onClickHandler = () => { setTheme( theme === "red"? "blue": "red"); } return ( <div> <Text theme={theme}/> <button onClick = {onClickHandler}>Change theme</button> </div> ); } function Text({theme}) { return( <h1 style = {{ color: `${theme}` }}>{theme}</h1> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);
이제 두 테마 간에 전환할 수 있습니다. 그러나 이것이 훨씬 더 큰 응용 프로그램이라면 깊이 중첩된 구성 요소에서 테마를 사용하기 어렵고 코드가 다루기 어려워집니다.
컨텍스트 API 소개
Context API를 소개하겠습니다. React 문서에 따르면:
"컨텍스트는 모든 수준에서 수동으로 props를 전달하지 않고도 구성 요소 트리를 통해 데이터를 전달할 수 있는 방법을 제공합니다."
보다 심층적인 정의를 위해 구성 요소가 얼마나 깊이 중첩되어 있더라도 구성 요소 트리의 모든 구성 요소에서 특정 데이터를 사용할 수 있도록 하는 방법을 제공합니다.
이 예를 살펴보겠습니다.
const App = () => { return( <ParentComponent theme = "light"/> ); } const ParentComponent = (props) => ( <Child theme = {props.theme} /> ) const Child = (props) => ( <Grandchild theme = {props.theme} /> ) const Grandchild = (props) => ( <p>Theme: {props.theme}</p> )
위의 예에서 우리는 theme
라는 ParentComponent
의 소품을 사용하여 애플리케이션 테마를 지정했습니다. GrandChild
구성 요소인 필요한 위치에 가져오기 위해 구성 요소 트리 아래의 모든 구성 요소에 해당 소품을 전달해야 했습니다. ChildComponent
는 테마 소품과 아무 관련이 없지만 중개자로만 사용되었습니다.
이제 GrandChild
구성 요소가 상위 예제보다 더 깊이 중첩되었다고 상상해 보십시오. 여기에서 했던 것과 같은 방식으로 테마 소품을 전달해야 하므로 번거롭습니다. 이것이 Context
가 해결하는 문제입니다. Context
를 사용하면 구성 요소 트리의 모든 구성 요소가 컨텍스트에 추가하기로 결정한 모든 데이터에 액세스할 수 있습니다.
Context
시작하기
이제 Context API를 사용하여 기사 시작 부분에서 만든 테마 토글 버튼을 복제할 차례입니다. 이번에는 테마 토글러가 별도의 구성 요소가 됩니다. Context
를 사용하여 React 앱의 테마를 전환하는 ThemeToggler
구성 요소를 빌드합니다.
먼저 React 앱을 초기화하겠습니다. (저는 create-react-app
을 사용하는 것을 선호하지만 원하는 방법을 사용할 수 있습니다.)
React 프로젝트를 초기화했으면 /src
폴더에 ThemeContext.js 라는 파일을 만듭니다. 원하는 경우 /context
라는 폴더를 만들고 거기에 ThemeContext 파일을 배치할 수도 있습니다.
이제 계속 진행하겠습니다.
컨텍스트 API 생성
ThemeContext.js 파일에 테마 컨텍스트를 생성합니다.
컨텍스트를 생성하기 위해 컨텍스트 객체를 생성하는 React.createContext
를 사용합니다. React.createContext
에 대한 인수로 무엇이든 전달할 수 있습니다. 이 경우 현재 테마 모드인 문자열을 전달합니다. 이제 현재 테마 모드는 "밝은" 테마 모드입니다.
import React from "react"; const ThemeContext = React.createContext("light"); export default ThemeContext;
이 컨텍스트를 모든 React 구성 요소에서 사용할 수 있도록 하려면 Provider를 사용해야 합니다. 공급자란 무엇입니까? React 문서에 따르면 모든 컨텍스트 개체에는 소비 구성 요소가 컨텍스트 변경 사항을 구독할 수 있도록 하는 Provider React 구성 요소가 함께 제공 됩니다. 컨텍스트를 다른 구성 요소에서 사용할 수 있도록 하는 것은 공급자입니다. 즉, 공급자를 생성해 보겠습니다.
App.js 파일로 이동합니다. 공급자를 생성하려면 ThemeContext
를 가져와야 합니다.
ThemeContext
를 가져온 후에는 App
구성 요소의 내용을 ThemeContext.Provider
태그로 ThemeContext.Provider
구성 요소에 구성 요소 트리에서 사용할 수 있도록 하려는 데이터를 포함하는 value
이라는 props를 제공해야 합니다.
function App() { const theme = "light"; return ( <ThemeContext.Provider value = {theme}> <div> </div> </ThemeContext.Provider> ); }
이제 "light"의 값을 모든 구성 요소에서 사용할 수 있습니다(곧 작성 예정).
테마 파일 만들기
이제 밝은 테마와 어두운 테마 모두에 대해 서로 다른 색상 값을 포함하는 테마 파일을 만듭니다. /src
폴더에 Colors.js 라는 파일을 만듭니다.
Colors.js 에서 AppTheme
라는 객체를 생성합니다. 이 개체에는 테마의 색상이 포함됩니다. 완료되면 다음과 같이 AppTheme
개체를 내보냅니다.
const AppTheme = { light: { textColor: "#000", backgroundColor: "#fff" }, dark: { textColor: "#fff", backgroundColor: "#333" } } export default AppTheme;
이제 다양한 React 구성 요소를 생성할 시간입니다.
React 구성 요소 만들기
다음 구성 요소를 만들어 보겠습니다.
-
Header
-
ThemeToggler
-
MainWithClass
헤더.jsx
import React from "react"; import ThemeToggler from "./ThemeToggler"; const headerStyles = { padding: "1rem", display: "flex", justifyContent: "space-between", alignItems: "center" } const Header = () => { return( <header style = {headerStyles}> <h1>Context API</h1> <ThemeToggler /> </header> ); } export default Header;
테마토글러.jsx
(지금은 빈 div
만 반환합니다.)
import React from "react"; import ThemeContext from "../Context/ThemeContext"; const themeTogglerStyle = { cursor: "pointer" } const ThemeToggler = () => { return( <div style = {themeTogglerStyle}> </div> ); } export default ThemeToggler;
클래스 기반 구성 요소로 컨텍스트 사용
여기에서 우리는 ThemeContext
의 값을 사용할 것입니다. 이미 알고 계시겠지만, React에서 컴포넌트를 작성하는 두 가지 방법이 있습니다: 함수 또는 클래스를 통해. 두 방법 모두 컨텍스트를 사용하는 프로세스가 다르기 때문에 애플리케이션의 주요 섹션으로 사용할 두 가지 구성 요소인 MainWithClass
및 MainWithFunction
을 만듭니다.
MainWithClass
부터 시작하겠습니다.
MainWithClass.jsx
ThemeContext
와 AppTheme
를 가져와야 합니다. 완료되면 렌더링 메서드에서 JSX를 반환하는 클래스를 작성합니다. 이제 컨텍스트를 소비해야 합니다. 클래스 기반 구성 요소로 이를 수행하는 두 가지 방법이 있습니다.
- 첫 번째 방법은
Class.contextType
을 사용하는 것입니다.
이 메서드를 사용하려면ThemeContext
의 컨텍스트 개체를 클래스의contextType
속성에 할당합니다. 그 후에this.context
를 사용하여 컨텍스트 값에 액세스할 수 있습니다. 또한 모든 수명 주기 메서드 및 렌더링 메서드에서도 이를 참조할 수 있습니다.import React, { Component } from "react"; import ThemeContext from "../Context/ThemeContext"; import AppTheme from "../Colors"; class Main extends Component{ constructor(){ super(); } static contextType = ThemeContext; render(){ const currentTheme = AppTheme[this.context]; return( <main></main> ); } }
클래스의contextType
속성에ThemeContext
를 할당한 후 현재 테마 객체를currentTheme
변수에 저장했습니다.
이제currentTheme
변수에서 색상을 가져와 일부 마크업의 스타일을 지정하는 데 사용합니다.render() { const currentTheme = AppTheme[this.context]; return ( <main style={{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main>
그게 다야! 그러나 이 방법은 하나의 컨텍스트만 사용하도록 제한합니다. - 두 번째 방법은 Consumer를 사용하는
ThemeContext.Consumer
입니다. 각 컨텍스트 개체에는 클래스 기반 구성 요소에서 사용할 수 있는 Consumer React 구성 요소도 함께 제공됩니다. 소비자 구성 요소는 자식을 함수로 사용하고 해당 함수는 React 노드를 반환합니다. 현재 컨텍스트 값이 해당 함수에 인수로 전달됩니다.
이제MainWithClass
구성 요소의 코드를 다음과 같이 교체해 보겠습니다.class Main extends Component { constructor() { super(); this.state = { } } render(){ return( <ThemeContext.Consumer> { (theme) => { const currentTheme = AppTheme[theme]; return( <main style = {{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main> ) } } </ThemeContext.Consumer> ); } }
보시다시피 "테마"로 별칭을ThemeContext
의 현재 값을 사용하고 해당 테마 모드의 색상 값을 가져와 변수currentTheme
에 할당했습니다. 이 방법을 사용하면 여러 소비자를 사용할 수 있습니다.
이것들은 클래스 기반 구성 요소로 컨텍스트를 사용하는 두 가지 방법입니다.
기능적 구성 요소로 컨텍스트 사용
기능적 구성 요소로 컨텍스트를 사용하는 것은 클래스 기반 구성 요소를 사용하는 것보다 쉽고 덜 지루합니다. 기능적 구성 요소에서 컨텍스트를 사용하려면 useContext
라는 후크를 사용합니다.
다음은 기능적 구성 요소로 ThemeContext
를 사용하는 방법입니다.
const Main = () => { const theme = useContext(ThemeContext); const currentTheme = AppTheme[theme]; return( <main style = {{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main> ); } export default Main;
보시다시피, 인수로 전달된 ThemeContext
와 함께 useContext
후크를 사용하기만 하면 됩니다.
참고 : 결과를 보려면 App.js 파일에서 이러한 다양한 구성 요소를 사용해야 합니다.
ThemeToggler
구성 요소로 테마 업데이트
이제 ThemeToggler
구성 요소에서 작업할 것입니다. 밝은 테마와 어두운 테마를 전환할 수 있어야 합니다. 이렇게 하려면 ThemeContext.js 를 편집해야 합니다. React.createContext
는 이제 useState
후크의 결과와 유사한 객체를 인수로 받습니다.
const ThemeContext = React.createContext(["light", () => {}]);
React.createContext
함수에 배열을 전달했습니다. 배열의 첫 번째 요소는 현재 테마 모드이고 두 번째 요소는 테마를 업데이트하는 데 사용할 함수입니다. 내가 말했듯이 이것은 useState
후크의 결과와 비슷하지만 정확히 useState
후크의 결과는 아닙니다.
이제 App.js 파일을 편집합니다. 공급자에게 전달된 값을 useState
후크로 변경해야 합니다. 이제 Theme Context의 값은 기본값이 "light"인 useState
후크입니다.
function App() { const themeHook = useState("light"); return ( <ThemeContext.Provider value = {themeHook}> <div> <Header /> <Main /> </div> </ThemeContext.Provider> ); }
ThemeToggler
구성 요소 작성
이제 실제로 ThemeToggler
구성 요소를 작성해 보겠습니다.
import React,{useContext} from "react"; import ThemeContext from "../Context/ThemeContext"; const themeTogglerStyle = { cursor: "pointer" } const ThemeToggler = () => { const[themeMode, setThemeMode] = useContext(ThemeContext); return( <div style = {themeTogglerStyle} onClick = {() => {setThemeMode(themeMode === "light"? "dark": "light")}}> <span title = "switch theme"> {themeMode === "light" ? "" : "️"} </span> </div> ); } export default ThemeToggler;
테마 컨텍스트의 값은 이제 useContext
를 호출할 때마다 후크이므로 배열을 반환합니다. Destructuring을 사용하여 배열에서 요소를 가져올 수 있었습니다. 그런 다음 ThemeToggler
용 onClick
이벤트 핸들러를 작성했습니다. 이 코드를 사용하면 테마 토글러를 클릭할 때마다 애플리케이션의 테마가 전환됩니다.
이제 Main
구성 요소의 다른 버전을 편집합니다.
MainWithClass
컴포넌트 편집하기
-
Class.contextType
메서드를 사용하는MainWithClass
구성 요소의 버전:import React, { Component } from "react"; import ThemeContext from "../Context/ThemeContext"; import AppTheme from "../Colors"; class Main extends Component{ constructor(){ super(); } static contextType = ThemeContext; render(){ const currentTheme = AppTheme[this.context[0]]; return( <main style={{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main> ); } }
-
ThemeContext.Consumer
메서드를 사용하는MainWithClass
구성 요소의 버전:import React, { Component } from "react"; import ThemeContext from "../Context/ThemeContext"; import AppTheme from "../Colors"; class Main extends Component { constructor() { super(); this.state = {} } render() { return ( <ThemeContext.Consumer> { ([theme]) => { const currentTheme = AppTheme[theme]; return( <main style = {{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main> ) } } </ThemeContext.Consumer> ); } } export default Main;
MainWithFunction
구성 요소 편집
MainWithFunction
구성 요소는 다음과 같이 편집해야 합니다.
import React, { useContext } from "react"; import ThemeContext from "../Context/ThemeContext"; import AppTheme from "../Colors"; const Main = () => { const theme = useContext(ThemeContext)[0]; const currentTheme = AppTheme[theme]; return( <main style = {{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main> ); } export default Main;
결론
그게 다야! Context API를 사용하여 React 앱에 대해 두 가지 테마 모드를 구현하는 데 성공했습니다.
그 과정에서 우리는 다음을 배웠습니다.
- Context API가 무엇이며 해결하는 문제
- 컨텍스트 API를 사용하는 경우
-
Context
생성 및 기능 및 클래스 기반 구성 요소 모두에서 사용
SmashingMag에 대한 추가 정보:
- 최신 웹 앱의 스타일링
- Ionic 및 React로 모바일 앱 구축
- Webpack 및 Workbox로 PWA 구축
- MutationObserver API 알아보기