본문 바로가기
Coding/React

React - next.js - styled components 셋팅

by z쿳쿳z 2022. 6. 24.
728x90
반응형

next js에서 styled components를 바로 적용한다면 다음과 같은 error가 발생한다. 이유는 SSR을 하는 next.js가 syled component를 먼저 못 읽어서 발생하는 문제이다.

 

#object

   * next js styled-components setting 하기

 

## setting - _app.tsx && _document.tsx

이 error 해결 하기위해서 _app.tsx 파일과 _document.tsx 파일을 custom 해야한다.

 

// _app.tsx

import type { AppProps } from "next/app";
import { ThemeProvider } from "styled-components";
import { theme } from "../styles/theme";
import Head from "next/head";
import App from "next/app";
import GlobalStyle from "../styles/GlobalStyle";

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <>
      <Head>
        <meta name='viewport' content='width=device-width, initial-scale=1' />
        <title>vloc-web-boilerplate</title>
      </Head>
      <GlobalStyle />
      <ThemeProvider theme={theme}>
        <Component {...pageProps} />
      </ThemeProvider>
    </>
  );
}

// Only uncomment this method if you have blocking data requirements for
// every single page in your application. This disables the ability to
// perform automatic static optimization, causing every page in your app to
// be server-side rendered.

MyApp.getInitailProps = async (appContext: any) => {
  // calls page's `getInitialProps` and fills `appProps.pageProps`
  const appProps = await App.getInitialProps(appContext);
};

export default MyApp;

 

// _document.tsx

import Document, {
  DocumentContext,
  DocumentInitialProps,
  Html,
  Head,
  Main,
  NextScript,
} from "next/document";
import React from "react";
import { ServerStyleSheet } from "styled-components";

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

    ctx.renderPage = () =>
      originalRenderPage({
        // Useful for wrapping the whole react tree
        enhanceApp: (App) => (props) => sheet.collectStyles(<App {...props} />),
        // Useful for wrapping in a per-page basic
        enhanceComponent: (Component) => Component,
      });

    // Run the parent `getInitialProps`, it now includes the custom `renderPage`
    const initialProps = await Document.getInitialProps(ctx);
    return {
      ...initialProps,
      styles: [
        <React.Fragment key={"Hello world"}>
          {initialProps.styles}
          {sheet.getStyleElement()}
        </React.Fragment>,
      ],
    };
  }

  render() {
    return (
      <Html>
        <Head>
          <meta charSet='utf-8' />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

export default MyDocument;

 

참조: 

  - https://styled-components.com/docs/advanced#nextjs

 

styled-components: Advanced Usage

Theming, refs, Security, Existing CSS, Tagged Template Literals, Server-Side Rendering and Style Objects

styled-components.com

  - https://nextjs.org/docs/advanced-features/custom-app

 

Advanced Features: Custom `App` | Next.js

Control page initialization and add a layout that persists for all pages by overriding the default App component used by Next.js.

nextjs.org

  - https://nextjs.org/docs/advanced-features/custom-document

 

Advanced Features: Custom `Document` | Next.js

Extend the default document markup added by Next.js.

nextjs.org

 

728x90
반응형