🧐[问题]在Nextjs13中按照文档中【SSR集成】中描述的方式使用,在通过createStyles写样式时会报错
ISproutNew opened this issue · comments
🧐 问题描述
在Next13通过App Router的方式创建的应用,按照文档说明创建了一个StyleRegistry组件并且在 app/layout.tsx中引入
import StyleRegistry from './StyleRegistry';
const RootLayout = ({ children }: PropsWithChildren) => (
<html lang="en">
<body>
<StyleRegistry>{children}</StyleRegistry>
</body>
</html>
);
然后在 app/page.tsx文件中
import { createStyles } from "antd-style";
const useStyles = createStyles(({ css }) => {
return {
main: css`
width: 100vw;
height: 100vh;
`,
};
});
export default function Home() {
const { styles } = useStyles();
return <main className={styles.main}>my home</main>;
}
产生的报错内容如下:
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
在app/page.tsx文件的头部添加 "use client" 就不会报错了。
并且我尝试在其他路由页面例如: app/about/page.tsx 使用createStyles书写样式也会得到同样的报错(不添加"use client"的情况下)。
是我使用的方式不对吗?还是说必须要添加"use client" ,我理解如果要添加"use client"那就意味着整个应用都是客户端组件了🤔
💻 示例代码
src/lib/StyleRegistry.tsx
"use client";
import { StyleProvider, extractStaticStyle } from "antd-style";
import { useServerInsertedHTML } from "next/navigation";
import { PropsWithChildren, useRef } from "react";
const StyleRegistry = ({ children }: PropsWithChildren) => {
const isInsert = useRef(false);
useServerInsertedHTML(() => {
// 避免多次渲染时重复插入样式
// refs: https://github.com/vercel/next.js/discussions/49354#discussioncomment-6279917
if (isInsert.current) return;
isInsert.current = true;
const styles = extractStaticStyle("").map(item => item.style);
return <>{styles}</>;
});
return (
<StyleProvider cache={extractStaticStyle.cache}>{children}</StyleProvider>
);
};
export default StyleRegistry;
src/app/layout.tsx
import Layout from "@/components/Layout";
import StyledComponentsRegistry from "@/lib/StyleRegistry";
import { ThemeToken } from "@/types/theme";
declare module "antd-style" {
export interface CustomToken extends ThemeToken {}
}
// Font files can be colocated inside of `app`
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html>
<body>
<StyledComponentsRegistry>
<Layout>{children}</Layout>
</StyledComponentsRegistry>
</body>
</html>
);
}
src/app/page.tsx
import { createStyles } from "antd-style";
const useStyles = createStyles(({ css }) => {
return {
main: css`
width: 100vw;
height: 100vh;
`,
};
});
export default function Home() {
const { styles } = useStyles();
return <main className={styles.main}>my home</main>;
}
🚑 其他信息
![image](https://private-user-images.githubusercontent.com/43919910/274139816-0e8c8ebc-998c-4618-b61b-268651dbf657.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjA2MDI0NjYsIm5iZiI6MTcyMDYwMjE2NiwicGF0aCI6Ii80MzkxOTkxMC8yNzQxMzk4MTYtMGU4YzhlYmMtOTk4Yy00NjE4LWI2MWItMjY4NjUxZGJmNjU3LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MTAlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzEwVDA5MDI0NlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWQ3MDNjODNlMzRlMGIzYmM4N2UwNjhmMTAxZWQ1NGU3YTQwN2NjY2JhMGUxYzBkMWI4YWE1OGU2YWEwZGY0YmUmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.RXOs5Yiu951CPqwuE6190jsHapAAlvWX36PWxt_VSFA)
是我使用的方式不对吗?还是说必须要添加"use client" ,我理解如果要添加"use client"那就意味着整个应用都是客户端组件了🤔
目前 CSSinJS 都是客户端渲染,所以必须要加 'use client' 的