React Starter Kit and Material UI: userAgent should be supplied in the muiTheme context for server-side rendering
Asked Answered
S

6

7

With the React Starter Kit, I add Material UI as follows:

npm install material-ui --save

and the following import to a component:

import RaisedButton from 'material-ui/lib/raised-button';

and:

<RaisedButton label="Default" />

I get the following error:

Warning: Material-UI: userAgent should be supplied in the muiTheme context for server-side rendering.

According to Material UI's documentation, it says I'd need to address three things:

  1. autoprefixer and the user agent
  2. process.env.NODE_ENV

What code should I put in and where exactly, specifically with the React Starter Kit?

P.S. this solution does not work for me :-/

Schoolteacher answered 18/2, 2016 at 12:8 Comment(0)
S
4

This works for me. Add this to server.js:

global.navigator = { userAgent: 'all' };

Then verify that you see multiple vendor prefixes used like in this screengrab showing -webkit and -ms both being used:

enter image description here

Schoolteacher answered 20/2, 2016 at 23:40 Comment(2)
This solution will lead for invalid checksum and display:-webkit-box,-moz-box,-ms-flexbox... please be careful, right now it will break your client behavior for support inline style prefixer which is trust the userAgentSpherule
Yes @IdanGozlan, I think this solution is better.Kimbrakimbrell
P
6

When using Material-UI with server rendering, we must use the same environment for the server and the client. This has two technical implications.

as you seen on MaterialUI documentation page

You need to provide the same user-agent for both server and browser contexts as you seen it in documentation, but, I strongly discourage you to provide a "all" user-agent, since you will serve a lot of unnecessary code to your end-user.

Instead you can easily follow MaterialUI doc and pass user-agent value contained in http request headers.

With an express or koa server

global.navigator = global.navigator || {};
global.navigator.userAgent = req.headers['user-agent'] || 'all';

I just checked it has been added to the ReactStarterKit (not tested myself) in src/server.js

global.navigator = global.navigator || {};
global.navigator.userAgent = global.navigator.userAgent || 'all';
Pigeon answered 29/6, 2016 at 13:10 Comment(1)
This will absolutely not work correctly server-side, as node can be servicing multiple requests concurrently (for different browsers), thereby overwriting the global value of global.navigator to be incorrect mid-cycle.Tyra
F
4

This should fix it

import themeDecorator from 'material-ui/lib/styles/theme-decorator';
import RaisedButton from 'material-ui/lib/raised-button';
import getMuiTheme from 'material-ui/lib/styles/getMuiTheme';

class MyComponent extends Component {
 render() {
   return (<RaisedButton label="Default" />);
  }
}

export default themeDecorator(getMuiTheme(null, { userAgent: 'all' }))(MyComponent);
Flabby answered 19/2, 2016 at 7:54 Comment(3)
I'm told to use MuiThemeProvider instead because themeDecorator has been deprecated.South
I agree that you should use MuiThemeProvider but getMuiTheme(null, { userAgent: 'all' }) still works, an in my opinion it's way more elegant than declaring a global variable.Cobwebby
Hi @RomanStarkov and GiladArtzi, I think you can do it this way.Kimbrakimbrell
S
4

This works for me. Add this to server.js:

global.navigator = { userAgent: 'all' };

Then verify that you see multiple vendor prefixes used like in this screengrab showing -webkit and -ms both being used:

enter image description here

Schoolteacher answered 20/2, 2016 at 23:40 Comment(2)
This solution will lead for invalid checksum and display:-webkit-box,-moz-box,-ms-flexbox... please be careful, right now it will break your client behavior for support inline style prefixer which is trust the userAgentSpherule
Yes @IdanGozlan, I think this solution is better.Kimbrakimbrell
S
3

Try adding global.navigator = { userAgent: 'all' }; at the top of your server.js file (Node.js entry point).

Superior answered 18/2, 2016 at 12:47 Comment(2)
Thanks. I've tried adding that at the very top (1st line) of server.js and again after all the imports - still getting the same warning.Schoolteacher
I had a look in the code and noticed that we'd need global.navigator.userAgent = 'all' not global.navigator = '' or global.navigator = 'all'. Will mention this in the GitHub discussion.Schoolteacher
L
3

The working (and the cleanest) solution for me is short and simple:

getMuiTheme({userAgent: (typeof navigator !== 'undefined' && navigator.userAgent) || 'all' })

Example (from my test app):

<MuiThemeProvider muiTheme={getMuiTheme({userAgent: (typeof navigator !== 'undefined' && navigator.userAgent) || 'all' })}>
    <Provider store={store}>
        <MyApplication/>
    </Provider>
</MuiThemeProvider>
Lorica answered 23/8, 2016 at 17:8 Comment(4)
This solution is incomplete, throws ReferenceError: navigator is not definedFur
Wrong. ReferenceError: navigator is not definedAsur
Hi @ThomasModeneis and Green, I think this solution is correct and working too: https://mcmap.net/q/1483597/-material-ui-how-to-properly-set-useragent-for-server-side-renderingKimbrakimbrell
its supposed to be global.navigator instead.Fur
M
0

If you are using KoaJS server you should install koa-useragent and then use this before server side rendering:

  global.navigator = global.navigator || {};
  global.navigator.userAgent = this.state.userAgent.source || 'all';

It worked for me !

Milano answered 17/7, 2016 at 15:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.