Next.js 样式组件奇怪的行为
Next.js Styled Components weird behaviour
所以我正在做一个项目,但我的边栏组件表现得有点奇怪:
我对 Components 了解不多,对 styled-components 了解更少,所以我什至不知道从哪里开始。
components/Sidebar.ts
import React, { useState } from 'react';
import { SidebarData } from './SidebarData';
import styled from 'styled-components';
import * as Remix from 'react-icons/ri';
import Submenu from './Submenu';
import { useSession } from 'next-auth/react';
/*
--text-color: #ffffff;
--text-secondary: #fefefe;
--background-color: #091540;
--background-secondary: #262c49;
--background-third: #1a254d;
--blue: #256EFF;
--red: #FF495C;
--green: #3DDC97;
*/
const Nav = styled.div`
background: #091540;
height: 8vh;
display: flex;
justify-content: flex-start;
align-items: center;
color: #ffffff;
`
const NavIcon = styled.div`
margin-left: 2vw;
font-size: 4vh;
height: 8vh;
display: flex;
justify-content: flex-start;
align-items: center;
cursor: pointer;
`
const SidebarNav = styled.div`
background: #091540;
width: 25vh;
height: 100%;
display: flex;
justify-content: center;
position: fixed;
top: 0;
left: ${({ sidebar }) => (sidebar ? '0' : '-100%')};
transition: 350ms;
z-index: 10;
color: #ffffff;
`
const SidebarWrap = styled.div`
width: 100%;
`
const Sidebar = () => {
const [sidebar, setSidebar] = useState(false);
const toggleSidebar = () => setSidebar(!sidebar);
const { data: session, status } = useSession();
return (
<div>
<Nav>
<NavIcon to="#">
<Remix.RiMenuFill onClick={toggleSidebar} />
</NavIcon>
</Nav>
<SidebarNav sidebar={sidebar}>
<SidebarWrap>
<NavIcon to="#">
<Remix.RiMenuFoldFill onClick={toggleSidebar}/>
</NavIcon>
{SidebarData.map((item, index) => {
if(session && item.disappearOnLogin === true && item.authRequired === false) return;
if(!session && item.disappearOnLogin === false && item.authRequired === true) return;
return <Submenu item={item} key={index}/>
})}
</SidebarWrap>
</SidebarNav>
</div>
)
}
export default Sidebar;
如果需要更多代码,请在 Discord 上私信我:magma#5090
所以基本上为了在服务器端渲染中使用样式化组件,您需要使用样式表再水化。当您的应用程序在服务器上呈现时,您可以创建一个 ServerStyleSheet 并向您的应用程序添加一个提供程序,该提供程序通过上下文 API.
接受样式
为此,您需要安装一个名为 babel-plugin-styled-components
的软件包
npm i babel-plugin-styled-components
然后,您想在项目的根目录中创建一个 .babelrc
文件,并将这些行添加到该文件中:
{
"presets": ["next/babel"],
"plugins": [["styled-components", { "ssr": true }]]
}
然后您想转到页面文件夹并创建一个 _document.js 页面。将以下代码添加到此文件中:
import Document from "next/document";
import { ServerStyleSheet } from "styled-components";
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
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();
}
}
}
有一种方法可以用 .tsx 文件做到这一点,但我不确定,使用 .js 文件对我有用,所以如果你愿意,我会让你找出 Typescript 版本。
重新启动您的服务器,您的样式化组件应该可以正常使用。
我不得不花很多时间来解决同样的问题。正如每个人在许多线程中提到的那样,我尝试创建 .babelrc 文件但没有解决我的问题。最后,我创建了 _document.tsx 文件并在 .babelrc 文件之外添加了以下代码。以下代码适用于任何找到打字稿版本的人。
import Document, {
Html,
Head,
Main,
NextScript,
DocumentContext,
} from "next/document";
import { ServerStyleSheet } from "styled-components";
export default class MyDocument extends Document {
static async getInitialProps(ctx: DocumentContext) {
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();
}
}
render() {
return (
<Html lang="en">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
所以我正在做一个项目,但我的边栏组件表现得有点奇怪:
我对 Components 了解不多,对 styled-components 了解更少,所以我什至不知道从哪里开始。
components/Sidebar.ts
import React, { useState } from 'react';
import { SidebarData } from './SidebarData';
import styled from 'styled-components';
import * as Remix from 'react-icons/ri';
import Submenu from './Submenu';
import { useSession } from 'next-auth/react';
/*
--text-color: #ffffff;
--text-secondary: #fefefe;
--background-color: #091540;
--background-secondary: #262c49;
--background-third: #1a254d;
--blue: #256EFF;
--red: #FF495C;
--green: #3DDC97;
*/
const Nav = styled.div`
background: #091540;
height: 8vh;
display: flex;
justify-content: flex-start;
align-items: center;
color: #ffffff;
`
const NavIcon = styled.div`
margin-left: 2vw;
font-size: 4vh;
height: 8vh;
display: flex;
justify-content: flex-start;
align-items: center;
cursor: pointer;
`
const SidebarNav = styled.div`
background: #091540;
width: 25vh;
height: 100%;
display: flex;
justify-content: center;
position: fixed;
top: 0;
left: ${({ sidebar }) => (sidebar ? '0' : '-100%')};
transition: 350ms;
z-index: 10;
color: #ffffff;
`
const SidebarWrap = styled.div`
width: 100%;
`
const Sidebar = () => {
const [sidebar, setSidebar] = useState(false);
const toggleSidebar = () => setSidebar(!sidebar);
const { data: session, status } = useSession();
return (
<div>
<Nav>
<NavIcon to="#">
<Remix.RiMenuFill onClick={toggleSidebar} />
</NavIcon>
</Nav>
<SidebarNav sidebar={sidebar}>
<SidebarWrap>
<NavIcon to="#">
<Remix.RiMenuFoldFill onClick={toggleSidebar}/>
</NavIcon>
{SidebarData.map((item, index) => {
if(session && item.disappearOnLogin === true && item.authRequired === false) return;
if(!session && item.disappearOnLogin === false && item.authRequired === true) return;
return <Submenu item={item} key={index}/>
})}
</SidebarWrap>
</SidebarNav>
</div>
)
}
export default Sidebar;
如果需要更多代码,请在 Discord 上私信我:magma#5090
所以基本上为了在服务器端渲染中使用样式化组件,您需要使用样式表再水化。当您的应用程序在服务器上呈现时,您可以创建一个 ServerStyleSheet 并向您的应用程序添加一个提供程序,该提供程序通过上下文 API.
接受样式为此,您需要安装一个名为 babel-plugin-styled-components
npm i babel-plugin-styled-components
然后,您想在项目的根目录中创建一个 .babelrc
文件,并将这些行添加到该文件中:
{
"presets": ["next/babel"],
"plugins": [["styled-components", { "ssr": true }]]
}
然后您想转到页面文件夹并创建一个 _document.js 页面。将以下代码添加到此文件中:
import Document from "next/document";
import { ServerStyleSheet } from "styled-components";
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
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();
}
}
}
有一种方法可以用 .tsx 文件做到这一点,但我不确定,使用 .js 文件对我有用,所以如果你愿意,我会让你找出 Typescript 版本。
重新启动您的服务器,您的样式化组件应该可以正常使用。
我不得不花很多时间来解决同样的问题。正如每个人在许多线程中提到的那样,我尝试创建 .babelrc 文件但没有解决我的问题。最后,我创建了 _document.tsx 文件并在 .babelrc 文件之外添加了以下代码。以下代码适用于任何找到打字稿版本的人。
import Document, {
Html,
Head,
Main,
NextScript,
DocumentContext,
} from "next/document";
import { ServerStyleSheet } from "styled-components";
export default class MyDocument extends Document {
static async getInitialProps(ctx: DocumentContext) {
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();
}
}
render() {
return (
<Html lang="en">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}