Snažím se použít některé proměnné exportované z globální .scss
soubor k vytvoření motivu UI materiálu. Problémy nastávají, protože tyto proměnné jsou undefined
na serveru (používám next.js
takže stránky jsou předem vykresleny). Jak to udělat?
Chyba, kterou dostanu (protože všechny barvy jsou 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.
Zde jsou důležité části mé aplikace.
_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;
}