1

Following the example in the next.js repo: https://github.com/zeit/next.js/tree/v3-beta/examples/with-material-ui

I can get Material-ui working for a single page. And i dont want to do the getInitialProps to set the userAgent prop on every page.

  • I tried making a HOC that I can use in my pages. But the getInitialProps only works for pages. so my MyMui component cant get the req object.
  • I tried creating the _document.js page, and wrapped the main with my MuiThemeProvider. But that gives me a bunch of errors.

So how can I get a clean solution to implement material-ui for all my pages?

Rob Indesteege
  • 548
  • 1
  • 8
  • 19

2 Answers2

2

I ran into a similar issue, and found a solution that looks like this:

// hocs/default-page.js
export default Page => class DefaultPage extends React.Component {
  static getInitialProps(ctx) {
    // Ensures material-ui renders the correct css prefixes server-side
    let userAgent
    if (process.browser) {
      userAgent = navigator.userAgent
    } else {
      userAgent = ctx.req.headers['user-agent']
    }

    // Check if Page has a `getInitialProps`; if so, call it.
    const pageProps = Page.getInitialProps && Page.getInitialProps(ctx);

    // Return props.
    return { ...pageProps, userAgent }
  }
  ...
  render() {
    return (
      <MuiThemeProvider ...>
        <Page/>
      </MuiThemeProvider>
    );
  }
}

// pages/index.js
import defaultPage from '../hocs/default-page';

const Page           = () => <h1>Hello World</h1>;
Page.getInitialProps = () => { ... };

export default defaultPage(Page);

// Also works for proper components:
export default defaultPage(class MyPage extends React.Component {

  static getInitialProps() {
    ...
  }

  render() {
    ...
  }

});
robertklep
  • 198,204
  • 35
  • 394
  • 381
  • Yep thanks, this works, I hope there is a cleaner, better solution though :) With this solution we cant use the getInitialProps in our pages anymore. – Rob Indesteege Jun 13 '17 at 20:56
0
  • layout.js

/**
 * Created by Counter on 5/30/2017.
 */
import React, {Component} from 'react'
import Head from 'next/head'
import RaisedButton from 'material-ui/RaisedButton'
import Dialog from 'material-ui/Dialog'
import Paper from 'material-ui/Paper';
import FlatButton from 'material-ui/FlatButton'
import getMuiTheme from 'material-ui/styles/getMuiTheme'
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'
import injectTapEventPlugin from 'react-tap-event-plugin'
import {blue100, blue400, blue700} from 'material-ui/styles/colors';
import AppBar from 'material-ui/AppBar';
import TextField from 'material-ui/TextField';

// Needed for onTouchTap
// http://stackoverflow.com/a/34015469/988941
try {
    if (typeof window !== 'undefined') {
        injectTapEventPlugin()
    }
} catch (e) {
    // do nothing
}

const styles = {


}

const _muiTheme = getMuiTheme({
    palette: {
        primary1Color: blue400,
        primary2Color: blue700,
        primary3Color: blue100,
    },
});


class Layout extends Component {

    render () {

        const { userAgent,children } = this.props
        /* https://github.com/callemall/material-ui/issues/3336 */
        const muiTheme = getMuiTheme(getMuiTheme({userAgent: userAgent}), _muiTheme)

        return (
            <MuiThemeProvider muiTheme={muiTheme}>
                <div>
                <Head>
                    <meta name="viewport" content="initial-scale=1.0, width=device-width"/>
                    <link rel='stylesheet' href='/static/css/react-md.light_blue-yellow.min.css'/>
                </Head>

                    {children}
                    </div>
            </MuiThemeProvider>

        )
    }
}

export default Layout
  • index.js

import React, {Component} from 'react'
import RaisedButton from 'material-ui/RaisedButton'
import Dialog from 'material-ui/Dialog'
import Paper from 'material-ui/Paper';
import FlatButton from 'material-ui/FlatButton'
import getMuiTheme from 'material-ui/styles/getMuiTheme'
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'
import injectTapEventPlugin from 'react-tap-event-plugin'
import {blue100,blue400, blue500, blue700,orange500} from 'material-ui/styles/colors';
import Layout from '../component/layout'
import AppBar from 'material-ui/AppBar';
import TextField from 'material-ui/TextField';
import {Tabs, Tab} from 'material-ui/Tabs';

// Needed for onTouchTap
// http://stackoverflow.com/a/34015469/988941
try {
    if (typeof window !== 'undefined') {
        injectTapEventPlugin()
    }
} catch (e) {
    // do nothing
}

const styles = {

    headline: {
        fontSize: 24,
        paddingTop: 16,
        marginBottom: 12,
        fontWeight: 400,
    },
    contentContainerStyle:{
        width:300,
        marginTop:133,
        float:'left'

    },
    floatingLabelStyle: {
        color: orange500,
    },
    floatingLabelFocusStyle: {
        color: blue500,
    },
    tabDiv:{
        textAlign:'center',
        backgroundColor: 'rgb(242, 244, 255);',
        boxShadow: '10px 10px 5px #888888',
        minHeight:350

    },
    button: {
        margin: 12,
    },
    descDiv:{
        width: '413px',
        float: 'left',
        margin: '133px 450px 0 25px',

    },
    outerDiv:{
        display:'inline-block'
    }

};

const _muiTheme = getMuiTheme({
    palette: {
        primary1Color: blue400,
        primary2Color: blue700,
        primary3Color: blue100,
    },
});


class Main extends Component {
    static getInitialProps ({ req }) {
        const userAgent = req ? req.headers['user-agent'] : navigator.userAgent
        const isServer = !!req
        return {isServer, userAgent}
    }

    constructor (props, context) {
        super(props, context);

        this.state = {
            clicked: false
        }
    }


    render () {

        const { userAgent } = this.props;
        return(
            <Layout userAgent={userAgent} >
                <div style={styles.outerDiv}>
                    <div style={styles.descDiv}>
                        <p>Lorem Ipsum is simply dummy text of the printing and
                            typesetting industry. Lorem Ipsum has been the
                            industry's standard dummy text ever since the 1500s,
                            when an unknown printer took a galley of type and
                            scrambled it to make a type specimen book. It has
                            survived not only five centuries, but also the leap
                            into electronic typesetting, remaining essentially
                            unchanged. It was popularised in the 1960s with the
                            release of Letraset sheets containing Lorem  </p>
                        <RaisedButton
                            target="_blank"
                            label="Test Your Api"
                            primary={true}
                            style={styles.button}
                            icon=''
                        />
                    </div>
                <Tabs
                    value={this.state.value}
                    onChange={this.handleChange}
                    style={styles.contentContainerStyle}


                >
                    <Tab label="Login" value="a">
                        <div style={styles.tabDiv}>
                            <TextField
                                floatingLabelText="Username"
                                floatingLabelStyle={styles.floatingLabelStyle}
                                floatingLabelFocusStyle={styles.floatingLabelFocusStyle}
                            />
                            <TextField
                                floatingLabelText="Password"
                                floatingLabelStyle={styles.floatingLabelStyle}
                                floatingLabelFocusStyle={styles.floatingLabelFocusStyle}
                            />
                            <br/>
                            <RaisedButton
                                target="_blank"
                                label="Submit"
                                secondary={true}
                                style={styles.button}
                                icon=''
                            />



                        </div>
                    </Tab>
                    <Tab label="SignUp" value="b">
                        <div style={styles.tabDiv}>
                            <TextField
                                floatingLabelText="Username"
                                floatingLabelStyle={styles.floatingLabelStyle}
                                floatingLabelFocusStyle={styles.floatingLabelFocusStyle}
                            />
                            <TextField
                                floatingLabelText="Password"
                                floatingLabelStyle={styles.floatingLabelStyle}
                                floatingLabelFocusStyle={styles.floatingLabelFocusStyle}
                            />
                            <TextField
                                floatingLabelText="Confirm Password"
                                floatingLabelStyle={styles.floatingLabelStyle}
                                floatingLabelFocusStyle={styles.floatingLabelFocusStyle}
                            />
                            <br/>
                            <RaisedButton
                                target="_blank"
                                label="Submit"
                                secondary={true}
                                style={styles.button}
                                icon=''
                            />

                        </div>
                    </Tab>
                </Tabs>

                    </div>

            </Layout>
        )


    }
}

export default Main
  • above files are from my project . i have created layout.js file which i have used in all the pages . this is one way to do it .
Rajat Gupta
  • 1,864
  • 1
  • 9
  • 17
  • yeah thats what i had, but what I didnt like about it is that you have to do the userAgent for every page you create, otherwise the SSR wont work for pages that dont have it. – Rob Indesteege Jun 14 '17 at 07:12
  • When your browser connects to a website, it includes a User-Agent field in its HTTP header. The contents of the user agent field vary from browser to browser. Each browser has its own, distinctive user agent. Essentially, a user agent is a way for a browser to say “Hi, I’m Mozilla Firefox on Windows” or “Hi, I’m Safari on an iPhone” to a web server. **This is a problem with material-ui it detects browser through user-agent and render page style according to that (in case of SSR). .you can also check out [react-md] (react-md.mlaursen.com) ,in react-md you dont have to do such thing** – Rajat Gupta Jun 14 '17 at 07:29