【问题标题】:How to use variables exported from .scss file to create Material-UI theme?如何使用从 .scss 文件中导出的变量来创建 Material-UI 主题?
【发布时间】:2020-09-29 19:04:20
【问题描述】:

我正在尝试使用从全局 .scss 文件中导出的一些变量来创建 Material-UI 主题。出现问题是因为这些变量是服务器上的undefined(我使用的是next.js,所以页面是预渲染的)。如何使这项工作?

我得到的错误(因为所有颜色都是undefined):

Error: Material-UI: The color provided to augmentColor(color) is invalid.
The color object needs to have a `main` property or a `500` property.

这是我的应用程序的重要部分。

_app.jsx

// General imports
import React from 'react';

// Components import
import App from 'next/app';
import { createMuiTheme, ThemeProvider, CssBaseline, StylesProvider, jssPreset } from '@material-ui/core';
import { create } from 'jss';

// Global styles and colors import
import '../styles/global.scss';
import colors from '../styles/colors.scss';

if (typeof document !== 'undefined') {
  const styleNode = document.createComment('jss-insertion-point');
  document.head.insertBefore(styleNode, document.head.firstChild);
}

/**
 * Material-UI theme.
 *
 * @type {Object}
 */
const theme = createMuiTheme({
  palette: {
    primary: {
      main: colors.primary,
      contrastText: colors.primaryText
    },
    secondary: {
      main: colors.secondary,
      contrastText: colors.secondaryText
    }
  }
});

class CustomApp extends App {
  /**
   * Handles the componentDidMount lifecycle event.
   *
   * @memberof MyApp
   */
  componentDidMount() {
    // Remove the server-side injected CSS.
    const jssStyles = document.querySelector('#jss-server-side');
    if (jssStyles) {
      jssStyles.parentElement.removeChild(jssStyles);
    }
  }

  /**
   * Renders the component.
   *
   * @returns component's elements
   * @memberof CustomApp
   */
  render() {
    const {
      Component,
      pageProps
    } = this.props;

    return (
     <>
        <StylesProvider
          jss={
            create({
              ...jssPreset(),
              // Define a custom insertion point that JSS will look for when injecting the styles into the DOM.
              insertionPoint: 'jss-insertion-point'
            })
          }
        >
          <ThemeProvider theme={theme}>
            <CssBaseline />
            <Component {...pageProps} />
          </ThemeProvider>
        </StylesProvider>
      </>
    );
  }
}

export default CustomApp;

_document.jsx

// General imports
import React from 'react';

// Components import
import Document, { Head, Main, NextScript } from 'next/document';
import { ServerStyleSheets } from '@material-ui/core';

/**
 *
 *
 * @class CustomDocument
 * @extends {Document}
 */
class CustomDocument extends Document {
  render() {
    return (
      <html lang="en">
        <Head>
          <meta charSet="utf-8" />
          <link rel="icon" href="/favicon.ico" />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </html>
    );
  }
}

CustomDocument.getInitialProps = async (ctx) => {
  // Render app and page and get the context of the page with collected side effects.
  const sheets = new ServerStyleSheets();
  const originalRenderPage = ctx.renderPage;

  ctx.renderPage = () => originalRenderPage({
    enhanceApp: (App) => (props) => sheets.collect(<App isServer {...props} />)
  });

  const initialProps = await Document.getInitialProps(ctx);

  return {
    ...initialProps,
    // Styles fragment is rendered after the app and page rendering finish.
    styles: [...React.Children.toArray(initialProps.styles), sheets.getStyleElement()],
    isServer: false
  };
};

export default CustomDocument;

colors.scss

$color-primary: #2aa876;
$color-primary-text: #ffffff;
$color-secondary: #ffd265;
$color-secondary-text: #7e621d;

:export {
  primary: $color-primary;
  primaryText: $color-primary-text;
  secondary: $color-secondary;
  secondaryText: $color-secondary-text;
}

【问题讨论】:

    标签: reactjs sass material-ui next.js


    【解决方案1】:

    Material UI 使用基于 javascript 的样式解决方案 (JSS),而不是像 SCSS (see style solution) 这样的 CSS 预处理器。

    这意味着无法通过 SCSS 变量自定义 Material UI 主题。也无法访问您的 CSS/SCSS 样式中的主题。

    如果您想使用 SCSS 进行样式/主题化,您可以考虑Material Web Components instead

    【讨论】:

    • 不确定我是否理解正确。无论如何,如果我写 createMuiTheme(colors.primary ? { ... } : { }) 会起作用,但用户会选择 FOUC。
    • @radovix 我认为将 SCSS 与 createMuiTheme 一起使用是不可能的。无论如何,如果你想在 MUI 中重用类或全局颜色,你可以创建一个外部样式文件,然后将该文件导入到要使用该样式的组件中,如下所示:stackoverflow.com/questions/62374323/…
    • 我也开始相信了。我设法使用 scss 文件中的颜色配置主题,但存在 FOUC。无论如何,感谢您的帮助。
    【解决方案2】:

    colors.scss中修改如下:

    $theme-colors: (
        'primary': #2aa876,
        'primaryText': #ffffff,
        'secondary': #ffd265,
        'secondaryText': #7e621d,
    );
    
    
    
    @each $color, $value in $theme-colours {
      :export{
        $color: $value;
      }
    }
    

    照你做的导入它。

    import colors from '../styles/colors.scss'; 
    # colors.primary and other variable should work now.
    

    【讨论】:

    • Syntax error: Selector ":export" is not pure (pure selectors must contain at least one local class or id)
    • 更新了答案。您可以在我更改导出时再次检查。
    • 错误不再存在,但这仍然不能解决我的问题。当这些颜色尚不可用时,可能由于预渲染而出现问题。
    猜你喜欢
    • 2021-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-06
    • 1970-01-01
    • 2021-05-11
    • 1970-01-01
    相关资源
    最近更新 更多