带有样式组件的 Nextjs 不通过主题

Posted

技术标签:

【中文标题】带有样式组件的 Nextjs 不通过主题【英文标题】:Nextjs with Styled components not passing theme 【发布时间】:2021-11-09 07:17:36 【问题描述】:

我正在尝试在我的 Next.js 项目中将我的主题对象传递给 styled-components,但它一直无法将其作为道具接收。

那是我的_document.tsx

import  getInitialProps  from "@expo/next-adapter/document";
import Document,   DocumentContext, DocumentInitialProps   from "next/document";
import  ServerStyleSheet  from "styled-components";

export default class MyDocument extends Document 
  static async getInitialProps(ctx: DocumentContext): Promise<DocumentInitialProps> 
    const sheet = new ServerStyleSheet();
    const originalRenderPage = ctx.renderPage;

    try 
      ctx.renderPage = () =>
        originalRenderPage(
          enhanceApp: (App) => (props) =>
            sheet.collectStyles(<App ...props />),
        );

      const initialProps = await getInitialProps(ctx);
      return 
        ...initialProps,
        styles: (
          <>
            initialProps.styles
            sheet.getStyleElement()
          </>
        ),
      ;
     finally 
      sheet.seal();
    
  

之后我用ThemeProvider包裹了我的_app.tsx

import Layout from '../components/Layout'
import 'setimmediate';
import  ThemeProvider  from 'styled-components';
import  wrapperStore  from "../store";
import  ApolloProvider  from "@apollo/client";
import client from './api/apollo-client';
import React from 'react';
import lightTheme from '../helpers/light-mode';
import  AppProps  from 'next/app';

function MyApp( Component, pageProps : AppProps) 

  return (
    <React.Fragment>
    <ApolloProvider client=client>
      <ThemeProvider theme=lightTheme>
        <Layout>
          <Component ...pageProps />
        </Layout>
      </ThemeProvider>
     </ApolloProvider>
    </React.Fragment>
  )

export default wrapperStore.withRedux(MyApp);

当我尝试包装我的组件并导出它withTheme时,我会收到一个警告@

[withTheme] You are not using a ThemeProvider nor passing a theme prop or a theme in defaultProps in component class "Connect(Front)"

当我尝试从我的道具控制台记录theme 时,它返回未定义,当我创建样式组件时,尝试使用theme 作为道具时会导致错误

export const RecruitmentTextLocation = styled.Text`
    fontSize: $scaleFont(15);
    textAlign: left;
    marginTop: $scale(5)px;
    marginBottom: $scale(1)px;
    fontFamily: roboto;
    fontWeight: 500;
    color: $(theme) => theme.colors.cardTitleColor;
`;

TypeError: Cannot read property 'colors' of undefined

我真的很纠结如何在 Nextjs 上将主题与样式化组件一起使用。

【问题讨论】:

【参考方案1】:

我想您的问题出在 light-mode.tsx 中。我怎么能看到你使用 typescript 在这种情况下需要创建一个 declarations 文件DefaultTheme 接口。 example

创建声明文件 从 v4.1.4 版本的定义开始,可以通过使用声明合并来扩展样式组件的 TypeScript 定义。 documentation

light-mode.tsx

import  DefaultTheme  from 'styled-components';

export const lightTheme: DefaultTheme = 
  colors: 
    cardTitleColor: red;
  
;

【讨论】:

【参考方案2】:

我一直在寻找相同的解决方案,并找到了一种解决方案,可以在样式化组件上键入您收到的作为道具的 theme 对象。

首先,导出你的主题类型,例如:

export type LightTheme = typeof lightTheme;

然后使用以下内容添加src/declaration.d.ts 文件,以便增强由styled-components 导出的DefaultTheme 以使用您的自定义主题对象键入:

import  Theme  from "globalStyles";

declare module "styled-components" 
  export interface DefaultTheme extends Theme 

从那里您将不需要任何withTheme 来使用您的主题对象,因为您只需通过以下方式访问它:

color: $(theme) => theme.colors.cardTitleColor;

【讨论】:

以上是关于带有样式组件的 Nextjs 不通过主题的主要内容,如果未能解决你的问题,请参考以下文章

带有主题的酶渲染样式组件

使用带有样式组件的 Material-UI 主题

包括对带有 typescript 的样式化组件主题的媒体查询

无法使用样式组件的 Nextjs 组件(链接)

NextJS 组件级 SASS 样式

如何在 next.js 中使用带有样式组件主题的 window.matchMedia?