The console.log(css)
returns some CSS as string (?)
The console.log(css)
returns empty string ""
. Therefore my rendered material-ui
components don't have styles.
I followed all steps in the official guide https://material-ui-next.com/guides/server-rendering/. And here is some sample of my code:
/* server.js */
...
import { SheetsRegistry, JssProvider } from 'react-jss';
import { create } from 'jss';
import preset from 'jss-preset-default';
import { MuiThemeProvider, createMuiTheme } from 'material-ui/styles';
import createGenerateClassName from 'material-ui/styles/createGenerateClassName';
import { red } from 'material-ui/colors';
...
app.use((req, res) => {
...
const sheetsRegistry = new SheetsRegistry();
const theme = createMuiTheme({
palette: {
primary: red,
type: 'dark',
},
});
const jss = create(preset());
jss.options.createGenerateClassName = createGenerateClassName;
const component = (
<Provider store={store} key="provider">
<JssProvider registry={sheetsRegistry} jss={jss}>
<MuiThemeProvider theme={theme} sheetsManager={new Map()}>
<ReduxAsyncConnect {...renderProps} />
</MuiThemeProvider>
</JssProvider>
</Provider>
);
const css = sheetsRegistry.toString();
console.log(css); // returns empty string
res.send(`<!doctype html>
${ReactDOM.renderToString(
<Html assets={webpackIsomorphicTools.assets()} style={css} component={component} store={store} />
)}`);
...
});
The response I got from initial render is correct, for example this AppBar
component
<AppBar>
<Toolbar>
<IconButton color="contrast" aria-label="Menu" className={classes.menuButton}>
<MenuIcon />
</IconButton>
<Typography type="title" color="inherit" className={classes.title}>
Dashboard
</Typography>
<Button color="contrast">Login</Button>
</Toolbar>
</AppBar>
Rendered to string as
<header class="c10 c16 c3 c4 c8 mui-fixed" data-reactid="4">
<div class="c37 c38" data-reactid="5">
<button tabindex="0" class="c48 c39 c41 c2" type="button" role="button" aria-label="Menu" data-reactid="6"><span class="c45" data-reactid="7"><svg class="c50 c46" focusable="false" viewBox="0 0 24 24" aria-hidden="true" data-reactid="8"><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z" data-reactid="9"></path></svg></span><span class="c51" data-reactid="10"></span>
</button>
<h2 class="c58 c64 c77 c1" data-reactid="11">Dashboard</h2>
<button tabindex="0" class="c48 c82 c87" type="button" role="button" data-reactid="12"><span class="c84" data-reactid="13">Login</span><span class="c51" data-reactid="14"></span>
</button>
</div>
</header>
Just trying to accomplish simple SSR by following official guide.
| Tech | Version |
|--------------|---------|
| Material-UI |1.0.0-beta.20|
| React |15.5.4|
| JSS | 8.1.0 |
| react-jss | 7.2.0 |
What you are describing is the expected behavior.
You are calling ReactDOM.renderToString()
after sheetsRegistry.toString()
.
You need to reverse the calls. It's ReactDOM.renderToString()
how is adding the CSS to the sheet registry.
@oliviertassinari Hi bro, I have the empty string problem too, but not like this calling renderToString
after sheetsRegistry.toString
, my problem is sheetsRegistry.toString
can generate stylesheet string correctly in the "first call", but after that, the sheetsRegistry.toString
just return empty string, I'm not sure if it's related to this one, so I just put it here first.
import { renderToString } from "react-dom/server";
import React from "react";
import { createGenerateClassName } from "material-ui/styles";
import { SheetsRegistry } from "react-jss/lib/jss";
import JssProvider from "react-jss/lib/JssProvider";
import Button from "material-ui/Button";
function render() {
const sheetsRegistry = new SheetsRegistry();
const generateClassName = createGenerateClassName();
const str = renderToString(
<JssProvider
registry={sheetsRegistry}
generateClassName={generateClassName}
>
<Button>Default</Button>
</JssProvider>
);
const css = sheetsRegistry.toString();
console.log(css.length);
}
render();
render();
The second console.log will print 0, what did I do wrong in SSR?
In case that you might need to reproduce it ssr
@cyl19910101 Posting this issue on StackOverflow would be much more efficient. The stylesheets are generated only once per component type (for performance). We use a cache. You need to clear this cache between two requests. It's what the sheetsManager
is for in the guide.
@oliviertassinari Thanks a lot! I was thinking that according to that guide if I don't need to override the default them then I don't need to wrap the application under MuiThemeProvider
....
@oliviertassinari @cyl19910101 so how can i clear cache? Lose many time for this problem..(
@Fi1osof The cache is stored in the sheetsManager
. It's a simple Map
object. You can provide a new one to clear the cache.
@oliviertassinari It`s my mistake... mui@next do not requries MuiThemeProvider, and i have not this component in my code. yes, later i added this component and this solves my problem. Thanks for answer!
@oliviertassinari Hi bro, I have the empty string problem too, but not like this calling
renderToString
aftersheetsRegistry.toString
, my problem issheetsRegistry.toString
can generate stylesheet string correctly in the "first call", but after that, thesheetsRegistry.toString
just return empty string, I'm not sure if it's related to this one, so I just put it here first.import { renderToString } from "react-dom/server"; import React from "react"; import { createGenerateClassName } from "material-ui/styles"; import { SheetsRegistry } from "react-jss/lib/jss"; import JssProvider from "react-jss/lib/JssProvider"; import Button from "material-ui/Button"; function render() { const sheetsRegistry = new SheetsRegistry(); const generateClassName = createGenerateClassName(); const str = renderToString( <JssProvider registry={sheetsRegistry} generateClassName={generateClassName} > <Button>Default</Button> </JssProvider> ); const css = sheetsRegistry.toString(); console.log(css.length); } render(); render();
The second console.log will print 0, what did I do wrong in SSR?
In case that you might need to reproduce it ssr
I had this issue too. Then I found that if I add sheetsManager={new Map()}
to MuiThemeProvider
, the problem solved.
Most helpful comment
What you are describing is the expected behavior.
You are calling
ReactDOM.renderToString()
aftersheetsRegistry.toString()
.You need to reverse the calls. It's
ReactDOM.renderToString()
how is adding the CSS to the sheet registry.