Next Js에서 localStorage다루기(feat Darkmode)

Mincho·2023년 6월 19일
0

[NextJs]

목록 보기
8/12

🔴 문제상황

  다음과 같이 다크 모드 적용을 위해 localstorage에 theme 저장 후 이 값을 가져와서 새로고침이 되더라도 theme를 유지하려 했다.

import { extendTheme, type ThemeConfig } from "@chakra-ui/react";

const initialColorMode = localStorage.getItem("chakra-ui-color-mode");

const config: ThemeConfig = {
  initialColorMode: initialColorMode,
  useSystemColorMode: true,
};

const theme = extendTheme({ config });

export default theme;

 그런데 위와 같이 localStorage를 찾지 못하고 있어서 문제 해결에 어려움이 있었다. 왜 localStorage를 찾지 못했을까??



🟠 원인

원인은 간단했다.

NextJS에서는 서버 사이드 렌더링 과정 중 window객체에 접근할 수 없다. 그렇기 때문에 window객체인 localStorage 또한 접근할 수 없었던 것이다. 서버 사이드 렌더링 후 클라이언트 사이드에서 접근을 해야 했다.



🟡 해결 과정

typeof window !== 'undefined'

페이지가 client에 마운트될 때까지 기다렸다가 localStorage에 접근해야했다 그러므로 window객체가 있을때 loacal저장소에 접근했다.

if (typeof window !== 'undefined') {
  localStorage.getItem('accesstoken');
}


===>> 적용방법
const initialColorMode =
  typeof window !== "undefined"
    ? localStorage.getItem("chakra-ui-color-mode")
    : null;

 하지만 문제는 계속 되었다.

UseEffect를 사용하여 적용하기

"use client";

import { CacheProvider } from "@chakra-ui/next-js";
import { ColorModeScript, ThemeConfig, extendTheme } from "@chakra-ui/react";
import dynamic from "next/dynamic";
import { useEffect, useState } from "react";
const ChakraProvider = dynamic(() =>
  import("@chakra-ui/provider").then((mod) => mod.ChakraProvider)
);

export function Providers({ children }: { children: React.ReactNode }) {
  const [initColor, setInitColor] = useState<string | null>("");

  useEffect(() => {
    const themeColor = localStorage.getItem("chakra-ui-color-mode");
    setInitColor(themeColor);
  }, []);

  const config: ThemeConfig = {
    initialColorMode: initColor,
    useSystemColorMode: true,
  };

  const theme = extendTheme({ config });

  return (
    <ChakraProvider theme={theme}>
      <ColorModeScript initialColorMode={theme.config.initialColorMode} />
      <CacheProvider>{children}</CacheProvider>
    </ChakraProvider>
  );
}

 useEffect를 사용해서 mount되었을 때 theme를 적용하였다. 참고로 react hook은 클라이언트 컴포넌트에서만 사용가능 하다는 것을 잊지말자.

 영상과 같이 적용이 잘되는 것을 확인할 수 있었다.

👍올바른 피드백은 언제든지 환영입니다~!

profile
사진찍는 개발자.

0개의 댓글