1

Problem: Cant seem to get styles to get sent down or loaded intially through ssr.

I'm following the docs and trying to do as it says, but styleSheets variable seems to be empty anyways. In my Navigation component i use JSS and use withStyles. From reading some of the documentation, using withStyles should populate my style sheets on my server right? However the variable that holds these styles ends up empty for some reason. Am i misinterpreting something?

serverRender.jsx

import React from 'react';
import { renderToString } from 'react-dom/server';
import { Provider } from 'react-redux';
import { RouterContext } from 'react-router';
import Helmet from 'react-helmet';
import serialize from 'serialize-javascript';
import { create } from 'jss';
import preset from 'jss-preset-default';
import { SheetsRegistry } from 'react-jss/lib/jss';
import JssProvider from 'react-jss/lib/JssProvider';
import { MuiThemeProvider, createMuiTheme } from 'material-ui/styles';
import createGenerateClassName from 'material-ui/styles/createGenerateClassName';
import { deepOrange, lightBlue, red } from 'material-ui/colors';
import staticAssets from './static-assets';
// import rtl from 'jss-rtl'; // in-case you're supporting rtl


const sheetsRegistry = new SheetsRegistry();

const theme = createMuiTheme({
  palette: {
    primary: deepOrange,
    secondary: lightBlue,
    error: red,
  },
});

// Configure JSS
const jss = create(preset());
jss.options.createGenerateClassName = createGenerateClassName;

const createApp = (store, props) => renderToString(
  <JssProvider registry={sheetsRegistry} jss={jss}>
    <MuiThemeProvider theme={theme} sheetsManager={new Map()}>
      <Provider store={store}>
        <RouterContext {...props} />
      </Provider>
    </MuiThemeProvider>
  </JssProvider>
);

//Grab our css from our sheetsRegistry
const registeredCss = sheetsRegistry.toString();

const buildPage = ({ componentHTML, initialState, headAssets, css }) => {
  return `
<!doctype html>
<html>
  <head>
    ${headAssets.title.toString()}
    ${headAssets.meta.toString()}
    ${headAssets.link.toString()}
    ${staticAssets.createStylesheets()}
    ${staticAssets.createTrackingScript()}
  </head>
  <body>
    <div id="app">${componentHTML}</div>
    <script>window.__INITIAL_STATE__ = ${serialize(initialState)}</script>
    ${staticAssets.createAppScript()}
    <style id="jss-server-side" type="text/css">${css}</style>
  </body>
</html>`;
};

export default (store, props) => {
  const initialState = store.getState();
  const componentHTML = createApp(store, props);
  const headAssets = Helmet.renderStatic();
  const css = registeredCss;
  console.log(css);
  return buildPage({ componentHTML, initialState, headAssets, css });
};

Here is where it should grab what we need for styling.

Where Navigation may look something like this:

import React, { Component } from 'react';
import { Link } from 'react-router';
import classNames from 'classnames/bind';
import AppBar from 'material-ui/AppBar';
import Toolbar from 'material-ui/Toolbar';
import Typography from 'material-ui/Typography';
import Button from 'material-ui/Button';
import IconButton from 'material-ui/IconButton';
import MenuIcon from 'material-ui-icons/Menu';
import { withStyles } from 'material-ui/styles';
import styles from '../css/components/navigation.css';

// import passTheAuxLogo from '../images/PassTheAux.png';

const styleSheet = ({
appbar: {
  width: '100%',
},

flex: {

},

menuButton: {
  marginLeft: -12,
  marginRight: 20,
},

navCenter: {
  display: 'flex',
  flex: 1
},
});

const cx = classNames.bind(styles);

class Navigation extends Component {

  constructor(props) {
    super(props);
    this.mobile = false;
  }
  render() {
    const mobile = this.mobile;
    const { classes } = this.props;
    return (
      <div className={classes.appbar}>
        <AppBar position="static" color="primary">
          <Toolbar>
            {mobile && (
            <IconButton className={classes.menuButton} color="contrast" aria-label="Menu">
              <MenuIcon />
            </IconButton>)}
            <Typography type="title" color="inherit" className={cx('flex')}>
              PassTheAux
            </Typography>
            <div className={classes.navCenter}>
              <Link to="/dashboard">
                <Button color="contrast">Dashboard</Button>
              </Link>

              <Link to="/about">
                <Button color="contrast">About</Button>
              </Link>

              <Link to="/404notfound">
                <Button color="contrast">404 Not Found</Button>
              </Link>
            </div>
            <Button color="contrast">Log In</Button>
            |
            <Button color="contrast">Sign up</Button>
          </Toolbar>
        </AppBar>
      </div>
    );
  }
}


export default withStyles(styleSheet)(Navigation);

Should the provider go around my app as well on the client? https://github.com/kkotwal94/KaranPRNB

EDIT: I guess another question on top of this one would be do I have to use JSS, can this be done if i wanted to use PostCSS?

1 Answer 1

3

You need to make sure the following flow of execution is respected:

  1. ReactDOM.renderToString() is called
  2. sheetsRegistry.toString() is called

It won't work the other way around as it's done in your GitHub repository.

Sign up to request clarification or add additional context in comments.

2 Comments

Im confused is it not in my repo? I see in the first codeblock of my question (serverRender.jsx) that i entered for the variable 'createApp' that im wrapping it with renderToString. Then when i generate my html below, I have {createApp} above {css}, where css calls sheetsRegistry.toString(). Am i derping hard or something?
Nevermind I see what you mean, const registeredCss = sheetsRegistry.toString(); I set this in the middle of no where, however this should be occuring after the fact I call createApp() in my export defaul method. Hence registeredCss is not filled with anything, thanks btw.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.