Client/Next.js

전역변수 상태관리 context API

Juzdalua 2024. 12. 4. 16:31

1. 먼저 사용할 전역 context 컴포넌트를 작성한다.

// global-context.tsx
import React, { useState, createContext, useContext } from "react";

// -> 여기에 사용할 변수들, 함수 인터페이스 작성
interface IGlobalContext {
  token: string | null;
  setToken: (token: string) => void;
}

const GlobalContext = createContext<IGlobalContext | undefined>(undefined);

export const GlobalContextProvider = ({ children }: { children: React.ReactNode }) => {
  const [token, setToken] = useState<string | null>(null);

  return <GlobalContext.Provider value={{ token, setToken }}>{children}</GlobalContext.Provider>;
};

export const useGlobalContext = () => useContext(GlobalContext);

 

2. context 컴포넌트를 최상위 루트로 설정한다.

보통 루트 url 컴포넌트인 app/page.tsx 파일에 설정한다고 하는데, 나는 레이아웃에서 token을 활용하고 싶어 layout 파일에 작성했다.

// src/app/layout.tsx

import "@/styles/global.css";
import { Metadata } from "next";
import MainComponent from "./(home)/components/main";

export const metadata: Metadata = {
  title: {
    template: "%s | Next.js",
    default: "Loading...",
  },
  description: "Generated by Next.js",
};

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body className="font-mono">
        <MainComponent>{children}</MainComponent> {/*메인컴포넌트에 작성함.*/} 
      </body>
    </html>
  );
}

// src/app/components/main.tsx
"use client";

import { useState } from "react";
import TopLayout from "./top-layout";
import Sidebar from "./sidebar";
import Footer from "./footer";
import { GlobalContextProvider } from "./global-context";

export default function MainComponent({ children }: { children: React.ReactNode }) {
  const [isSidebarVisible, setIsSidebarVisible] = useState(false);

  return (
    <div>
      <GlobalContextProvider> {/*사용할 컴포넌트 상위에 작성*/}
        <TopLayout onSideBarToggle={() => setIsSidebarVisible(!isSidebarVisible)} />
        <div className="flex">
          <Sidebar isVisible={isSidebarVisible} />
          <div className={`${isSidebarVisible ? "ml-56" : ""} flex-1 h-screen`}>{children}</div>
        </div>
        <Footer />
      </GlobalContextProvider>
    </div>
  );
}

 

3. 사용 예제

// src/app/auth/logout/page.tsx

"use client";

import LocalStorage from "@/src/utils/LocalStorage";
import { useRouter } from "next/navigation";
import { useEffect } from "react";
import { useGlobalContext } from "../../(home)/components/global-context";

const Logout = () => {
  const router = useRouter();
  const { token, setToken } = useGlobalContext(); // -> 인터페이스에 작성한 변수 중 사용할 것들

  useEffect(() => {
    LocalStorage.removeItem("jwt");
    setToken(null); // -> 전역 변수 null로 변환

    router.push("/");
  }, [router]);
};

export default Logout;

// OTHER_page.tsx
...
const { token, setToken } = useGlobalContext();

useEffect(() => {
if (token) {
  router.push("/");
}
}, [router]);
 ...

 

react를 잘 모르는 상태에서 최대한 외부 라이브러리 없이 적용하고 싶었다.

vue에서는 localStorage만으로도 상태관리가 됐었던 것 같던데, 그렇게 적용하니 새로고침을 계속 해야 적용됐다.

아무튼 context API를 활용해서 잘 적용됐다.

 

'Client > Next.js' 카테고리의 다른 글

Next.js app router 규칙 - API 라우트 (13 버전 이상)  (0) 2025.01.10
Next.js) 커스텀 서버를 사용하여 WebSocket 통신하기  (1) 2024.12.13
css module  (0) 2024.11.27
병렬 fetch, Suspense  (1) 2024.11.27
Loading Component  (0) 2024.11.27