개발조각

[모두의 이력서_13일차] Next.js TS에서 Styled-components 적용 안되는 에러 본문

모두의 이력서

[모두의 이력서_13일차] Next.js TS에서 Styled-components 적용 안되는 에러

개발조각 2023. 4. 7. 13:16
728x90
반응형

작업을 하다 보니 큰 틀? theme.ts, global.ts, _app.tsx를 수정할 경우

styled-components가 풀리는 현상이 발생했습니다.

 

(다시 오류를 구현하려다가 안 나와서 다른 사람 오류캡처를 들고 왔습니다.)

- 저도 이거랑 똑같이 `className` did not match. 오류가 났습니다.

이렇게 css가 다 풀린 상태에서요.

 

이유

Next가 먼저 정적으로 생성된 HTML을 렌더후 나머지 JS파일을 로드하게 됩니다.

JS에 의해 동적으로 CSS가 생성되는 CSS-In-Js 방식인 styled-components는 위와 같은 과정에서 생성되는 HTML에 우리의 코드가 함께 빌드되지 않습니다.

 

해결법

renderPage 함수를 커스터마이징을 통해 해결해야됩니다.

renderPage 함수 커스터마이징은 반드시 CSS-In-Js 방식 사용 할 때만 수정하라고 합니다.

 

1. _document.tsx 파일 추가

pages
|- _document.tsx
// _document.tsx
import Document, { DocumentContext, DocumentInitialProps } from "next/document";
import { ServerStyleSheet } from "styled-components";

export default class MyDocument extends Document {
  static async getInitialProps(
    ctx: DocumentContext
  ): Promise<DocumentInitialProps> {
    const sheet = new ServerStyleSheet();
    const originalRenderPage = ctx.renderPage;

    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: (App) => (props) =>
            sheet.collectStyles(<App {...props} />),
        });

      const initialProps = await Document.getInitialProps(ctx);
      return {
        ...initialProps,
        styles: [
          <>
            {initialProps.styles}
            {sheet.getStyleElement()}
          </>,
        ],
      };
    } finally {
      sheet.seal();
    }
  }
}

 

2. .babelrc 파일 추가

`className` did not match.는 바벨로 해결했습니다.

 

위 에러는 서버에서 받은 해시 + 클래스명과 새로고침후 클라이언트에서 받은 해시 + 클래스명이 달라서 발생하는 문제이기 때문입니다.

 

npm i babel-plugin-styled-components
front // 최상단 디렉토리
|- .babelrc
// .babelrc
{
  "presets": ["next/babel"],
  "plugins": ["babel-plugin-styled-components"]
}

 

3. 기존에 설정한 next/font 제거하기

구문 오류: 사용자 지정 바벨 구성이 있기 때문에 바벨이 사용되고 있지만 "next/font"에는 SWC가 필요합니다.

이렇게 하면 모든 에러가 끝이 날줄 알았는데 이런 오류가 나네요;;;ㅎㅎ

제가 이전에 next에서 구글 폰트를 설정해서 생긴 오류입니다.

그래서 지웠습니다...

// _app.tsx
import { useState } from "react";
import Head from "next/head";
import { AppProps } from "next/app";
import { Noto_Sans_KR } from "next/font/google"; // 지움
import { useRouter } from "next/router";
import { ThemeProvider } from "styled-components";

import Header from "../components/layout/header/Header";
import Float from "../components/layout/Float";

import theme from "../styles/theme";
import Global from "../styles/global";
import { ThemeContext } from "../context/themeContext";

// 지움
const notoSansKr = Noto_Sans_KR({
  subsets: ["latin"],
  weight: ["300", "400", "500", "700"],
});

const _app = ({ Component }: AppProps) => {
  const router = useRouter();

  const derkMode =
    typeof window !== "undefined" ? localStorage.getItem("isDark") : null;
  const [isDark, setIsDark] = useState(derkMode ? true : false);
  const mode = isDark ? "darkTheme" : "lightTheme";

  console.log("a");

  return (
    <>
      <Head>
        <title>모두의 이력서</title>
        <meta name="description" content="Generated by create next app" />
        <link rel="icon" href="/favicon.png" />
      </Head>

      <main className={notoSansKr.className}> // 지움
        <ThemeContext.Provider value={{ isDark, setIsDark }}>
          <ThemeProvider theme={theme}>
            <Global mode={mode} />
            {router.query.header !== "N" && <Header />}
            <Float />
            <Component />
          </ThemeProvider>
        </ThemeContext.Provider>
      </main>
    </>
  );
};

export default _app;

 

 

참고자료


https://velog.io/@hongdol/Next.js-TS-%EB%A6%AC%EB%A0%8C%EB%8D%94%EB%A7%81%EC%8B%9C-Styled-Components-%EC%A0%81%EC%9A%A9-%EC%95%88%EB%90%98%EB%8A%94-%EC%97%90%EB%9F%AC

 

Next.js TS 리렌더링시 Styled-Components 적용 안되는 에러

Next와 styled-components를 쓰게 되면 브라우저 로딩이 끝나야 CSS 적용이 되거나 새로고침을하게되면 css가 적용이 안된다.Next가 먼저 정적으로 생성된 HTML을 렌더후 나머지 JS파일을 로드하게 된다.JS

velog.io

 

https://yoon990.tistory.com/54

 

[WEB] Next.js + Typesctipt + StyledComponents 프로젝트 생성하기

이번에 새로운 사이드프로젝트를 진행하면서 기술 스택들이 정해졌고, 해당 스택들을 사용해서 프로젝트를 생성하려고 한다. react와 scss로 작업해본 경험이 있어서 이번엔 크게 next.js (react를 했

yoon990.tistory.com

 

728x90
반응형
Comments