그동안은 따로 뭔가 세팅하는 게 싫어서(귀찮아서) sass를 썼는데, 이번 프로젝트에서는 atomic design system을 제대로 써보고싶어서 styled components를 세팅해보았다.
next.js doc: styling css in js
'use client'
import React, { useState } from 'react'
import { useServerInsertedHTML } from 'next/navigation'
import { ServerStyleSheet, StyleSheetManager } from 'styled-components'
export default function StyledComponentsRegistry({
children,
}: {
children: React.ReactNode
}) {
// Only create stylesheet once with lazy initial state
// x-ref: https://reactjs.org/docs/hooks-reference.html#lazy-initial-state
const [styledComponentsStyleSheet] = useState(() => new ServerStyleSheet())
useServerInsertedHTML(() => {
const styles = styledComponentsStyleSheet.getStyleElement()
styledComponentsStyleSheet.instance.clearTag()
return <>{styles}</>
})
if (typeof window !== 'undefined') return <>{children}</>
return (
<StyleSheetManager sheet={styledComponentsStyleSheet.instance}>
{children}
</StyleSheetManager>
)
}
styled components로 생성된 모든 css를 수집하는 글로벌 레지스트리 컴포넌트 생성.
그리고 useServerInsertedHTML 훅을 사용해서 루트 레이아웃의 html 태그에 넣어준다. 라는데 그냥 위에서 생성한 컴포넌트를 body 하위에서 children 감싸주는 형태로 넣으면 된다.
import "./globals.css";
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import StyledComponentsRegistry from "@/lib/registry";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className={inter.className}>
<StyledComponentsRegistry>{children}</StyledComponentsRegistry>
</body>
</html>
);
}