일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- MVC
- react
- assertequals
- Thymeleaf
- localStorage
- JDBC
- JavaScript
- git reset
- git amend
- Java
- oracle
- useContext
- BCryptPasswordEncoder
- passwordencoder
- CRUD
- mybatis
- git
- WHEREIN
- content-box
- PathVariable
- HTML
- SQL
- Variabla
- springboot
- 이딴게개발자
- 배열
- Spring
- git revase
- ResultType
- 부적합한열
- Today
- Total
개발새발
[React] React Hook - useContext 본문
React에는 컴포넌트 간 데이터를 전달하는 대표적인 방법이 두 가지가 있는데,
그 중 하나가 바로 props
props는 데이터를 간편하게 넘기고 받을 수 있다는 장점이 있지만 어떤 상황에서는 굉장히 큰 문제가 된다
1. 컴포넌트 트리 구조가 굉장히 복잡하고 깊을 경우
2. 위의 상황에서 자식 컴포넌트로 데이터를 전달하는 경우
소규모의 리액트 앱이라든지, 혹은 데이터 전달을 원하는 자식 컴포넌트가 부모 컴포넌트 바로 밑에 존재한다면 별 문제는 되지 않을 것이다.
하지만 자식의, 자식의, 자식의, 자식의, 자식의, ... , 자식의 컴포넌트에게 데이터를 전달 할 때는 어떻게 할 것인가?
컴포넌트 전체에 공통적으로 필요한 데이터가 존재할 경우에는 어떻게 할 것인가?
이를테면 현재 로그인 된 사용자 정보, 사이트 테마, 언어 정보 등등 ...
언제든 앱 내부에서는 수많은 컴포넌트에 쓰일 전역적 데이터가 존재할 수 있기 마련이다.
이러한 전역적 데이터를 props로 일일이 단계별로 전달하게 된다면 코드의 복잡도는 물론이고,
어느 한 곳에서 변경사항이 생기는 순간 이에 적용된 컴포넌트를 죄다 쥐잡듯 뒤져 찾아내서 수정해야하는 불상사가 일어난다
그래서 등장한 것이 바로 context API 라고 할 수 있겠다
1. Context
앱 내부에서 전역적으로 사용되는 데이터들을
여러 컴포넌트들끼리 쉽게 공유할 수 있는 방법을 제공해주는 API
context를 사용하게 된다면, props로 데이터를 일일이 전달하지 않아도 해당 데이터를 지닌 상위 컴포넌트는 하위 컴포넌트가 트리 어디에 위치해있든지 상관 없이 데이터에 바로 접근 할 수 있도록 해준다.
아래와 같은 컴포넌트 트리 구조를 가진 앱이 있다고 가정하자.
이때 App이 지니고 있는 데이터를 C, E 컴포넌트에서 필요로 하는 상황이다.
props를 사용한다면 데이터 전달을 어떻게 할 것인가?
보다시피 트리의 가장 하단에 존재하는 C,E에서만 데이터가 필요함에도 불구하고
데이터 전달 과정에서 불필요하게 모든 중간 컴포넌트를 거쳐야 한다.
2. useContext
context로 공유한 데이터를 쉽게 받아올 수 있도록 도와주는 hook
하지만 context를 사용할 경우는 어떻게 될 것인가?
C와 E 컴포넌트에서 useContext hook을 사용하면 다른 컴포넌트를 거칠 필요가 없이 직접적으로 데이터를 받아올 수 있기에 아주 편리하다!
따라서 이번 글에서는 useContext를 활용한 간단한 테마변경 코드를 작성해보겠다
어떤 페이지를 만들 것인가?
header, content, footer로 구성되며
footer에 있는 mode 버튼을 통해 light / dark 모드 적용이 가능한 페이지
어떻게 만들 것인가?
1. context를 생성하는 별도의 컴포넌트 사용
2. header, content, footer에서 useContext를 사용하여 context 받아오기
1. ThemeContext.js
import {createContext} from 'react';
//기본값 null
export const ThemeContext = createContext(null);
createContext를 이용해 ThemeContext를 생성
2. App.js
import React,{useState} from 'react';
import '../../css/App.css';
import Page from './Page';
import { ThemeContext } from './ThemeContext';
export default function App() {
const [isDark, setIsDark] = useState(false);
return(
//prop으로 value를 받음 > 전달하고자하는 데이터를 넣어준다
//ThemeContext.Prodiver가 감싸는 모든 하위 component는 value로 집어넣어준 요소에 접근 가능해진다
<ThemeContext.Provider value={{isDark, setIsDark}} >
<Page />
</ThemeContext.Provider>
);
}
- useState를 사용해서 isDark 기본값 false(light모드)로 세팅
- ThemeContext를 import 하고, ThemeContext.Provider를 통해 트리 안에 포함된 컴포넌트에 value를 전달
3. Headr.js & Content.js
import React, { useContext } from "react";
import { ThemeContext } from "./ThemeContext";
//props로 isDark 받아옴
export default function Header() {
const {isDark} = useContext(ThemeContext);
return(
<header className="header"
style={{
backgroundColor : isDark ? 'black' : 'lightgray',
color : isDark ? 'white' : 'black',
}}
>
<h1>Welcome Page</h1>
</header>
)
}
import React, { useContext } from "react";
import { ThemeContext } from "./ThemeContext";
export default function Content(){
const {isDark} = useContext(ThemeContext);
return(
<div
className="content"
style={{
backgroundColor : isDark ? 'black' : 'white',
color : isDark ? 'white' : 'black',
}}
>
<p>오늘도 좋은 하루~~^^</p>
<p>꽃 한 송이 놓고 갑니다 @/-----</p>
</div>
)
}
- useContext를 통해 props로 isDark 받아오기
- 삼항 연산자를 통해 isDark의 상태에 따라 달라지는 style 적용
4. Footer.js
import React, { useContext } from "react";
import { ThemeContext } from "./ThemeContext";
export default function Footer(){
const {isDark, setIsDark} = useContext(ThemeContext);
const toggleTheme = () => {
setIsDark(!isDark);
};
return(
<footer
className="footer"
style={{
backgroundColor : isDark ? 'black' : 'lightgray',
}}
>
<button className="button" onClick={toggleTheme}>
Dark Mode
</button>
</footer>
)
}
- toggleTheme 함수를 생성해서 하단 버튼 누를시 isDark의 state 변경
5. Page.js
import React from "react";
import Content from './Content';
import Footer from './Footer';
import Header from './Header';
//isDark, setIsDark를 props로 받아와서 또 다른 자식 컴포넌트에 전달
//Page 자체에서는 isDark를 사용하지 않기 때문에, 단지 그냥 중간 컴포넌트의 역할을 한다
export default function Page() {
return(
<div className="page">
<Header />
<Content />
<Footer />
</div>
);
};
- header / content / footer 컴포넌트를 묶어서 한 페이지를 꾸려줌
App.js 실행 결과
css는 따로 적용한거긴한데 그거 아니어도 작동은 잘 합니다
이렇게 보니까 굳이 Page를 통해서 props를 전달할 필요가 없다는 점에서 context가 굉장히 편해보이고,
실제로도 그렇긴 하지만
당연하게도 context 사용에도 주의사항이 존재한다.
바로 컴포넌트 재사용이 어렵기 때문에 필요에 따라 적절하게 사용을 해야한다는 점..
따라서 단순히 prop drilling을 피하고싶어서 context를 사용하려한다면 컴포넌트 합성 등
다른 방안을 먼저 고안해보는 것도 방법이 될 수 있겠다
나도 자유자재로 쓰고싶은 hook... 익숙해질 날이 오겠지?
'FRONT > React' 카테고리의 다른 글
로그인, 로그아웃 상태에 따른 화면 구현에 대한 고찰 (0) | 2024.01.20 |
---|---|
[React] React와 DB를 연결하기 위한 환경 설정 (feat.Oracle) (0) | 2023.12.26 |
[React] React 사용을 위한 환경 설정 (0) | 2023.12.18 |