文章目录
- 使styled-component 像SPA中使用
step1 安装插件
step2 根目录下创建 `.babelrc`
step3 创建`page/_document.js`自定义 Document
参考 特别感谢
[应用主题] 需完成上一步
-
- yarn add babel-plugin-styled-components
- { "presets": [ "next/babel" ], // 覆盖nextjs的默认babel配置,以本文件的babel配置为准 "plugins": [ [ "styled-components", { "ssr": true } // 预编译样式 ] ]}
- import Document, { Html, Head, Main, NextScript } from 'next/document'import { ServerStyleSheet } from 'styled-components'class MyDocument extends Document { static async getInitialProps(ctx) { const sheet = new ServerStyleSheet() // 1.这里采用react里High Order Component的方式,可以重新包装APP和所有渲染的组件 const originalRenderPage = ctx.renderPage try { ctx.renderPage = () => originalRenderPage({ enhanceApp: App => (props) => // App挂载样式 sheet.collectStyles(<App {...props} />) }) // 因为覆盖了Document,所以要重新返回页面的props const props = await Document.getInitialProps(ctx) return { ...props, styles: <>{props.styles}{sheet.getStyleElement()}</> } } finally { sheet.seal() } } render() { return ( <Html> <Head> </Head> <body> <Main /> <NextScript /> </body> </Html> ) }}export default MyDocument
- _document.js的文档styled-components 服务端渲染 nextJS styled-components 集成
- _app.js 只加入一个 ThemeProvide 具体在 ThemeProvide 中 import type { AppProps } from "next/app";import ThemeProvide from "../context/ThemeProvide";function MyApp({ Component, pageProps }: AppProps) { return ( <ThemeProvide> <Component {...pageProps} /> </ThemeProvide> );}export default MyApp; ThemeProvide import { createContext, useState, useCallback, ReactNode, useContext,} from "react";import { ThemeProvider } from "styled-components";import { useMount } from "../hooks";export const lightTheme = { primary: "#51f", fg: "#fff", bg: "#000", mode: "light",};const darkTheme = { primary: "#083f2c", fg: "#000", bg: "#eee", mode: "dark",};const ThemeContext = createContext<undefined | (() => void)>(undefined);export const useToggleTheme = () => useContext(ThemeContext);const ThemeProvide = ({ children }: { children: ReactNode }): JSX.Element => { const [theme, setTheme] = useState(lightTheme); const toggleMode = useCallback(() => { setTheme(({ mode }) => { const newMode = mode == "dark" ? lightTheme : darkTheme; localStorage.setItem("MODE", newMode.mode); console.log("new theme mode:" + newMode.mode); return newMode; }); }, []); useMount(() => { const oldMode = localStorage.getItem("MODE"); if (oldMode && oldMode != theme.mode) { toggleMode(); } }); return ( <ThemeContext.Provider value={toggleMode}> <ThemeProvider theme={theme}>{children}</ThemeProvider> </ThemeContext.Provider> );};export default ThemeProvide; useMount import { useEffect } from "react";const useMount = (callback: any) => { // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(callback, []);};export default useMount;
-
- 使styled-component 像SPA中使用
- step1 安装插件
- step2 根目录下创建 `.babelrc`
- step3 创建`page/_document.js`自定义 Document
- 参考 特别感谢
- [应用主题] 需完成上一步
yarn add babel-plugin-styled-components
{
"presets": [
"next/babel"
], // 覆盖nextjs的默认babel配置,以本文件的babel配置为准
"plugins": [
[
"styled-components",
{
"ssr": true
} // 预编译样式
]
]
}
"presets": [
"next/babel"
], // 覆盖nextjs的默认babel配置,以本文件的babel配置为准
"plugins": [
[
"styled-components",
{
"ssr": true
} // 预编译样式
]
]
}
import Document, { Html, Head, Main, NextScript } from 'next/document'
import { ServerStyleSheet } from 'styled-components'
class MyDocument extends Document {
static async getInitialProps(ctx) {
const sheet = new ServerStyleSheet()
// 1.这里采用react里High Order Component的方式,可以重新包装APP和所有渲染的组件
const originalRenderPage = ctx.renderPage
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: App => (props) =>
// App挂载样式
sheet.collectStyles(<App {...props} />)
})
// 因为覆盖了Document,所以要重新返回页面的props
const props = await Document.getInitialProps(ctx)
return {
...props,
styles: <>{props.styles}{sheet.getStyleElement()}</>
}
} finally {
sheet.seal()
}
}
render() {
return (
<Html>
<Head>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument
import { ServerStyleSheet } from 'styled-components'
class MyDocument extends Document {
static async getInitialProps(ctx) {
const sheet = new ServerStyleSheet()
// 1.这里采用react里High Order Component的方式,可以重新包装APP和所有渲染的组件
const originalRenderPage = ctx.renderPage
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: App => (props) =>
// App挂载样式
sheet.collectStyles(<App {...props} />)
})
// 因为覆盖了Document,所以要重新返回页面的props
const props = await Document.getInitialProps(ctx)
return {
...props,
styles: <>{props.styles}{sheet.getStyleElement()}</>
}
} finally {
sheet.seal()
}
}
render() {
return (
<Html>
<Head>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument
_document.js的文档styled-components 服务端渲染
nextJS styled-components 集成
_app.js 只加入一个 ThemeProvide 具体在 ThemeProvide 中
import type { AppProps } from "next/app";
import ThemeProvide from "../context/ThemeProvide";
function MyApp({ Component, pageProps }: AppProps) {
return (
<ThemeProvide>
<Component {...pageProps} />
</ThemeProvide>
);
}
export default MyApp;
ThemeProvide
import {
createContext,
useState,
useCallback,
ReactNode,
useContext,
} from "react";
import { ThemeProvider } from "styled-components";
import { useMount } from "../hooks";
export const lightTheme = {
primary: "#51f",
fg: "#fff",
bg: "#000",
mode: "light",
};
const darkTheme = {
primary: "#083f2c",
fg: "#000",
bg: "#eee",
mode: "dark",
};
const ThemeContext = createContext<undefined | (() => void)>(undefined);
export const useToggleTheme = () => useContext(ThemeContext);
const ThemeProvide = ({ children }: { children: ReactNode }): JSX.Element => {
const [theme, setTheme] = useState(lightTheme);
const toggleMode = useCallback(() => {
setTheme(({ mode }) => {
const newMode = mode == "dark" ? lightTheme : darkTheme;
localStorage.setItem("MODE", newMode.mode);
console.log("new theme mode:" + newMode.mode);
return newMode;
});
}, []);
useMount(() => {
const oldMode = localStorage.getItem("MODE");
if (oldMode && oldMode != theme.mode) {
toggleMode();
}
});
return (
<ThemeContext.Provider value={toggleMode}>
<ThemeProvider theme={theme}>{children}</ThemeProvider>
</ThemeContext.Provider>
);
};
export default ThemeProvide;
useMount
import { useEffect } from "react";
const useMount = (callback: any) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(callback, []);
};
export default useMount;

© 版权声明
文章版权归作者所有,未经允许请勿转载。