본문 바로가기

React

[React] useContext 사용법 및 예제

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