해결된 질문
23.12.14 10:31 작성
·
1.5K
0
안녕하세요, 강의는 수강중이기도하고 아래에 비슷한 맥락의 질문이 있는데 제가 이해한게 맞나 궁금해서
질문 올립니다!
현재 next14 버전과 styled-component를 사용중이며 공식문서
https://nextjs.org/docs/app/building-your-application/styling/css-in-js#styled-components
내용 과 검색등을 통하여 적용하였습니다.
// libs/styledCompnents/Registry.tsx
'use client';
import { useServerInsertedHTML } from 'next/navigation';
import { ReactNode, useState } from 'react';
import { ServerStyleSheet, StyleSheetManager } from 'styled-components';
const Registry = ({ children }: { children: ReactNode }) => {
const [styledComponentsStyleSheet] = useState(() => new ServerStyleSheet());
useServerInsertedHTML(() => {
const styles = styledComponentsStyleSheet.getStyleElement();
styledComponentsStyleSheet.instance.clearTag();
return <>{styles}</>;
});
if (typeof document !== 'undefined') {
return <>{children}</>;
}
return (
<StyleSheetManager sheet={styledComponentsStyleSheet.instance}>
{children}
</StyleSheetManager>
);
};
export default Registry;
//libs/styledComponets/Provider.tsx
'use client';
import { ThemeProvider } from 'styled-components';
import GlobalStyles from '@/styles/GlobalStyles';
import theme from '@/styles/theme';
import { PropsWithRequiredChildren } from '@/types/common';
import { StyledComponentsRegistry } from '.';
const Providers = (props: PropsWithRequiredChildren) => {
return (
<StyledComponentsRegistry>
<ThemeProvider theme={theme}>
<GlobalStyles />
{props.children}
</ThemeProvider>
</StyledComponentsRegistry>
);
};
export default Providers;
// layout.tsx
import type { Metadata } from 'next';
import { Inter } from 'next/font/google';
import AdminLayout from '@/layouts/AdminLayout/AdminLayout';
import { StyledComponentsProvider } from '@/libs/styledComponents';
import { MSWComponent } from '@/mocks/MSWComponent';
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}>
<MSWComponent>
<StyledComponentsProvider>
<AdminLayout>{children}</AdminLayout>
</StyledComponentsProvider>
</MSWComponent>
</body>
</html>
);
}
현재 이렇게 사용중인데 AdminLayout에 'use client'를 사용하지않으면, 아래와 같은 에러가 나오고
'use client' 를 사용하면 에러 없이 렌더링이 정상적으로 됩니다.
```
Error: createContext only works in Client Components. Add the "use client" directive at the top of the file to use it. Read more: https://nextjs.org/docs/messages/context-in-server-component
This error happened while generating the page. Any console logs will be displayed in the terminal window.
node_modules/styled-components/dist/styled-components.esm.js (1:15911)
next/server/vendor-chunks/styled-components.js (30:1)
next/server/webpack-runtime.js (33:42)
webpack-internal:///(rsc)/./src/components/atoms/Text/Text.style.ts (5:75)
next/server/app/page.js (569:1)
next/server/webpack-runtime.js (33:42)
webpack-internal:///(rsc)/./src/components/atoms/Text/Text.tsx (7:69)
next/server/app/page.js (580:1)
next/server/webpack-runtime.js (33:42)
webpack-internal:///(rsc)/./src/components/atoms/Text/index.ts (5:63)
next/server/app/page.js (591:1)
next/server/webpack-runtime.js (33:42)
webpack-internal:///(rsc)/./src/layouts/AdminLayout/AdminLayout.tsx (10:80)
next/server/app/page.js (745:1)
next/server/webpack-runtime.js (33:42)
webpack-internal:///(rsc)/./src/app/layout.tsx (10:90)
next/server/app/page.js (503:1)
next/server/webpack-runtime.js (33:42)
/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js (35:401280)
/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js (35:405046)
/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js (35:405596)
/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js (35:409938)
/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js (35:410457)
```
궁금한 점이 3가지가 있는데 검색만으로는 이해가 잘안되서 질문드립니다ㅠ
1. AdminLayout이 'use client'를 선언하지 않고 서버 컴포넌트로 사용을 하여도 StyledComponentsProvider 가 'use client' 이기 때문에 클라이언트 컴포넌트의 자식으로 AdminLayout을 사용하면 AdminLayout도 자동으로 클라이언트 컴포넌트로 변경되는걸까요? 아니면 자식 요소로 사용하는것은 상관없이 import 해오는 경우만 클라이언트 컴포넌트에서 서버 컴포넌트를 불러오면 서버 컴포넌트가 클라이언트 컴포넌트가 되는걸까요?
2. 컴포넌트의 자식이 부모의 컴포넌트의 상태를 따라간다면, 만약 최상위 부모 (Layout)가 클라이언트 컴포넌트라면 어차피 AdminLayout 이나 불러오는 NavMenu 들을 서버 컴포넌트로 사용 못하는게 맞나요?
3. 강의상 진행할때는 문제 없었습니다. 현재 위에 질문드린 에러는 styled-components 때문에 createContext 는 use client에서만 사용할수있다라는 에러인거같은데 AdminLayOut이나 다른 페이지에서도 useContext를 사용하려하면 'use client'를 작성하여도 같은 에러가 나옵니다. 현재 말씀드린 정보로만으로는 에러의 문제점을 찾을순 없을까요?
답변 1
0
2023. 12. 14. 10:38
클라이언트가 서버컴포넌트를 import하면 서버 컴포넌트가 클라이언트 컴포넌트가 됩니다. 서버컴포넌트가 클라이언트컴포넌트를 임포트하는건 아무 영향 없습니다.
네 그런데 서버컴포넌트를 import가 아니라 props로 전달하면 서버컴포넌트로 쓸 수 있습니다. children도 props라 서버컴포넌트를 전달 가능하고요. 레이아웃은 서버컴포넌트로 놔두는 게 좋습니다.
일단 서버 재시작 및 .next 삭제 해보시고 스타일드 컴포넌트를 쓴 곳을 전부 use client로 해보세요.
2023. 12. 14. 11:41
아하 답변 감사합니다. 현재 이렇게 style.ts에서 styled-component 를 불러와서 S. 으로 사용하여 Layout에 이벤트나 훅이 들어가지 않는데도 'use client'를 사용해야 에러가 일어나지않았던거군요