简体   繁体   中英

How to use variables exported from .scss file to create Material-UI theme?

I'm trying to use some variables exported from global .scss file to create Material-UI theme. Problems occurs because those variables are undefined on server (I'm using next.js so pages are pre-rendered). How to make this work?

Error that I get (beacuse all colors are 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.

Here are the important parts of my application.

_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;
}

Material UI uses a javascript based style solution (JSS) instead of a CSS pre-processor like SCSS ( see style solution ).

This means it's not possible to customize the Material UI theme via SCSS variables. Nor is it possible to access the theme in your CSS/SCSS styles.

If you want to use SCSS for styling/theming, you might consider Material Web Components instead .

In colors.scss modify as below:

$theme-colors: (
    'primary': #2aa876,
    'primaryText': #ffffff,
    'secondary': #ffd265,
    'secondaryText': #7e621d,
);


@each $color, $value in $theme-colors {
  :export{
    $color: $value;
  }
}

import it as you're doing.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM