useContext
useContext를 사용하지 않으면, 부모 컴포넌트에서 자식 컴포넌트로 props를 통해서 데이터를 전달한다.
이런식으로 여러개의 컴포넌트가 있다고 가정하면 루트 컴포넌트에서 최하위 컴포넌트로 순차적으로 전달할 때 엄청난 노가다가 될 수 있다. 하지만 context를 사용하면 전역적으로 데이터를 공유하기 때문에 루트에서 최하위 컴포넌트로 다이렉트로 데이터를 한번에 전달할 수 있다.
useContext 예제
ex1)
AuthContext.ts
useContext를 사용하기 위해 ThemeContext에 초기값 null을 설정하였다.
useState를 사용하여 isDark 초기값 false로 설정하고,
ThemContext.Provider 을 이용하여 value값 isDark와 setIsDark를 전달하였다.
import { createContext, useState } from "react";
export const ThemeContext = createContext(null);
export const AuthContext = (props) => {
const [isDark, setIsDark] = useState(false);
return (
<ThemeContext.Provider value={{ isDark, setIsDark }}>
{props.children}
</ThemeContext.Provider>
)
}
App.js
Page를 AuthContext의 컴포넌트로 감싸 Page 컴포넌트에서는 isDark, setIsDark를 사용할 수 있게 되었다.
import './App.css';
import Page from './componets/Page';
import { AuthContext } from './context/AuthContext';
function App() {
return (
<AuthContext>
<Page />
</AuthContext>
);
}
export default App;
Page.js
Page컴포넌트에는 Header, Content, Footer이 있다.
import React from "react";
import Content from "./Content";
import Footer from "./Footer.js";
import Header from "./Header";
const Page = () => {
return (
<div className="page">
<Header />
<Content />
<Footer />
</div>
);
};
export default Page;
Header.js
useContext 훅을 사용하여 ThemeContext를 불러온다.
import React, { useContext } from "react";
import { ThemeContext } from "../context/AuthContext";
const Header = () => {
const { isDark } = useContext(ThemeContext);
return (
<header
className="header"
style={{
backgroundColor: isDark ? "black" : "lightgrey",
color: isDark ? "white" : "black",
}}
>
<h1>Welcome!!</h1>
</header>
);
};
export default Header;
Content.js
import React, { useContext } from "react";
import { ThemeContext } from "../context/AuthContext";
const Content = () => {
const { isDark } = useContext(ThemeContext);
return (
<div
className="content"
style={{
backgroundColor: isDark ? "black" : "lightgrey",
color: isDark ? "white" : "black",
}}
>
<p>좋은 하루 되세요</p>
</div>
);
};
export default Content;
Footer.js
버튼을 클릭했을때 배경색을 변경해줘야하므로 isDark, setIsDark가 필요하다.
useContext 훅을 사용하여 ThemeContext를 불러와 사용였다.
import React, { useContext } from "react";
import { ThemeContext } from "../context/AuthContext";
const Footer = () => {
const { isDark, setIsDark } = useContext(ThemeContext);
const handleClick = () => {
setIsDark(!isDark);
}
return (
<footer
className="footer"
style={{
backgroundColor: isDark ? "black" : "lightgrey",
}}
>
<button className="button" onClick={handleClick}>
click me!!!
</button>
</footer>
);
};
export default Footer;
ex2 )
ThemContext.tsx
firebase user 컬렉션에 있는 사용자들 === 현재 로그인한 사용자 uid가 일치한 사용자 이름을 가져왔다.
(useState를 이용하여 userName에 저장)
useContext를 사용하기 위해 ThemeContext에 초기값 null을 설정하였고,
ThemContext.Provider 을 이용하여 value값 userName을 전달하였다.
import {
ReactNode,
useEffect,
useState,
} from "react";
import { collection, getDocs } from "firebase/firestore";
import { auth, db } from "../../../firebase";
import React from "react";
export const ThemeContext = React.createContext(null);
interface IProps {
children: ReactNode;
}
export const AuthContext = (props: IProps) => {
const CollectionRef = collection(db, "user");
const [userName, setUserName] = useState<string>("");
useEffect(() => {
const getUserName = async () => {
const data = await getDocs(CollectionRef);
const user = auth.currentUser;
data.docs
.map((doc) => ({
...doc.data(),
}))
.filter((doc) => {
if (user?.uid === doc.uid) {
return setUserName(doc.userName);
}
});
};
getUserName();
}, []);
return (
<ThemeContext.Provider value={{ userName }}>
{props.children}
</ThemeContext.Provider>
);
};
App.tsx
AuthContext 컴포넌트를 App.tsx 상위에 넣어 모든 컴포넌트들이 userName을 사용할 수 있도록 하였다.
useContext를 사용한 이유는 로그인된 회원 이름이 다른 탭을 누를때마다 계속 렌더링되어 깜빡거리는걸 해결하기 위해서 사용하였는데
AuthContext 컴포넌트 안에 Home이 있어 userName을 전달하였다.(Home 안에 navbar가 있음)
export const App: React.FunctionComponent = () => {
return (
<AuthContext>
<ConfigProvider locale={locale}>
<BrowserRouter>
<ScrollToTop />
<Routes>
<Route
path="/views/user-roles"
element={<UserRoles />}
/>
<Route path="/views/login" element={<Login />} />
<Route path="*" element={<NotFoundPage />} />
<Route path="/" element={<Home />} />
</Route>
</Routes>
</BrowserRouter>
</ConfigProvider>
</AuthContext>
);
};
export default hot(App);
Home.tsx
export const Home: React.FunctionComponent = () => {
return (
<Layout>
<Header />
<Introduce />
<Solution />
<Employ />
</Layout>
);
};
Navbar.tsx
ThemContext에 있는 userName을 불러와서 사용할 수 있다.
export const Navbar = () => {
const { userName } = useContext(ThemeContext);
return (
<span className="user-name">
{userName} // ThemContext에 있는 userName을 불러옴
</span>
)
}
<참고>
별코딩 react useContext
https://www.youtube.com/watch?v=LwvXVEHS638
'React' 카테고리의 다른 글
[React] Recoil 사용법 (0) | 2022.09.20 |
---|---|
[React] Redux란? (0) | 2022.09.15 |
[React] Hook 정리 (0) | 2022.09.13 |
[React] 다중 파일 전송 material ui, axios (0) | 2022.07.27 |
[React] useReducer 사용법 (0) | 2022.07.24 |