Material-ui: Warning: Failed child context type: Invalid child context of type `Jss` supplied to `JssProvider`, expected instance of `Jss`. in JssProvider

Created on 18 Oct 2017  ·  16Comments  ·  Source: mui-org/material-ui

I used material-ui@next as server side render and do all things as the documents. But my console says
Warning: Failed child context type: Invalid child context `64a55d578f856d258dc345b094a2a2b3` of type `Jss` supplied to `JssProvider`, expected instance of `Jss`. in JssProvider (at server.js:274)
Here are the code around line 274
````
const jss = create(preset());
jss.options.createGenerateClassName = createGenerateClassName;

const rootComponent = (
  <JssProvider registry={sheetsRegistry} jss={jss}>
    <MuiThemeProvider theme={theme} sheetsManager={new Map()}>
      <App context={context} store={store}>
        {route.component}
      </App>
    </MuiThemeProvider>
  </JssProvider>
);

````
Is there some things wrong? Thanks for help.

external dependency

Most helpful comment

I'm having the same issue right now, following the create-react-app demo.

All 16 comments

As far as I know, @kof plan an making the contextType constraint more permissive.

This warning is coming from a duplicated version of jss. Make sure you are using the same one.
Maybe we should be using jss as a peer dependency.

As far as I know, @kof plan an making the contextType constraint more permissive.

I did, will release with the next react-jss version

@oliviertassinari Thanks for help,

@oliviertassinari I'm getting the same error but with a different setup.

I'm trying to bring the new material-ui to my existing next.js project. I have followed the example at
Material UI next.js examplr

Warning: Failed prop type: Invalid prop `jss` of type `Jss` supplied to `JssProvider`, expected instance of `Jss`.
    in JssProvider (at _document.js?entry:63)
    in Unknown
    in AppContainer
    in Container
    in div
    in App
Warning: Failed prop type: Invalid prop `registry` of type `SheetsRegistry` supplied to `JssProvider`, expected instance of `SheetsRegistry`.
    in JssProvider (at _document.js?entry:63)
    in Unknown
    in AppContainer
    in Container
    in div
    in App
Warning: Failed context type: Invalid context `64a55d578f856d258dc345b094a2a2b3` of type `Jss` supplied to `Component`, expected instance of `Jss`.
    in withStyles(AppWrapper) (at withRoot.js:50)
    in MuiThemeProvider
    in MuiThemeProviderWrapper (at withRoot.js:46)
    in withRoot(withStyles(Component)) (at _document.js?entry:64)
    in JssProvider (at _document.js?entry:63)
    in Unknown
    in AppContainer
    in Container
    in div
    in App

Everything works exactly as expected except for these warning that I get. The only difference that my setup has is I'm using custom server ExpressJS besides next.js but I'm not sure how it causes these warnings to show up. Here is my server code. Should I follow ExpressJS integration as documented on the website or Next.js example should be enough.

const { configureRoutes } = require('./routes');
const dev = process.env.NODE_ENV !== 'production';
const logger = require('./utilities/logger').logger;
const app = next({ dev });
const handle = app.getRequestHandler();

app.prepare()
    .then(() => {
        const server = express();
        server.use(compress());
        server.use(bodyParser.json());
        server.use(bodyParser.urlencoded({ extended: true }));
        // Routes should be configured here.
        configureRoutes(server);
        server.get('*', (req, res) => {
            return handle(req, res);
        });

        server.listen(3000, (err) => {
            if (err) throw err;
            logger.info('>>>> Ready on http://localhost:3000');
        });
    })
    .catch((ex) => {
        logger.error(ex.stack);
        process.exit(1);
    });

Maybe you should check whether you inject css directly into context, my warnings occur here.

@WenXuanYuan I followed the example and basically have two main files:

getContext.js

// @flow weak
/* eslint-disable no-underscore-dangle */
/* Code is taken from https://github.com/callemall/material-ui/blob/v1-beta/examples/nextjs/styles/getContext.js */


import { create, SheetsRegistry } from 'jss';
import preset from 'jss-preset-default';
import { createMuiTheme } from 'material-ui/styles';
import purple from 'material-ui/colors/purple';
import green from 'material-ui/colors/green';
import createGenerateClassName from 'material-ui/styles/createGenerateClassName';

const theme = createMuiTheme({
    palette: {
        primary: purple,
        secondary: green,
    },
});

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

function createContext() {
    return {
        jss,
        theme,
        // This is needed in order to deduplicate the injection of CSS in the page.
        sheetsManager: new Map(),
        // This is needed in order to inject the critical CSS.
        sheetsRegistry: new SheetsRegistry(),
    };
}

export default function getContext() {
    // Make sure to create a new store for every server-side request so that data
    // isn't shared between connections (which would be bad)
    if (!process.browser) {
        return createContext();
    }
    // Reuse context on the client-side
    if (!global.__INIT_MATERIAL_UI__) {
        global.__INIT_MATERIAL_UI__ = createContext();
    }
    return global.__INIT_MATERIAL_UI__;
}

And _document.js which is the top document for all Nextjs pages

/**
 * This document will be used to overide the head of all of your htmls,
  so we can include bundle.css here.
 */

import Document, { Head, Main, NextScript } from 'next/document';
import React from 'react';
import JssProvider from 'react-jss/lib/JssProvider';
import getContext from '../utils/getContext';

class MyDocument extends Document {
    render() {
        return (
            <html lang="en" dir="ltr">
                <Head>
                    <title>My page</title>
                    <meta charSet="utf-8" />
                    {/* Use minimum-scale=1 to enable GPU rasterization */}
                    <meta
                        name="viewport"
                        content={
                  'user-scalable=0, initial-scale=1, ' +
                  'minimum-scale=1, width=device-width, height=device-height'
                }
                    />
                    {/*
                        {/* PWA primary color */}
                    <meta
                        name="theme-color"
                        content={this.props.stylesContext.theme.palette.primary[500]}
                    />
                    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" />
                </Head>
                <body>
                    <Main />
                    <NextScript />
                </body>
            </html>
        );
    }
}

MyDocument.getInitialProps = (ctx) => {
    // Resolution order
    //
    // On the server:
    // 1. page.getInitialProps
    // 2. document.getInitialProps
    // 3. page.render
    // 4. document.render
    //
    // On the server with error:
    // 2. document.getInitialProps
    // 3. page.render
    // 4. document.render
    //
    // On the client
    // 1. page.getInitialProps
    // 3. page.render
    // Get the context to collected side effects.
    const context = getContext();
    const page = ctx.renderPage(Component => props => (
        <JssProvider registry={context.sheetsRegistry} jss={context.jss}>
            <Component {...props} />
        </JssProvider>
    ));
    return {
        ...page,
        stylesContext: context,
        styles: (
            <style
                id="jss-server-side"
                // eslint-disable-next-line react/no-danger
                dangerouslySetInnerHTML={{ __html: context.sheetsRegistry.toString() }}
            />
        ),
    };
};

export default MyDocument;

These are all copied from the official examples, the only difference that I have is custom Express integration that I pasted the code above. I really can't tell what I should change.

I got this error too. And I find it everything OK when I using my mac during server rending, css will generate. But on windows, the sheetsRegistry.toString only generate css once. And after the first time, I will never get css generated. what's the promble?
My server rendering code here:

const serialize = require('serialize-javascript')
const ejs = require('ejs')
const asyncBootstrap = require('react-async-bootstrapper').default
const ReactDomServer = require('react-dom/server')
const Helmet = require('react-helmet').default

const SheetsRegistry = require('react-jss').SheetsRegistry
const createJss = require('jss').create
const preset = require('jss-preset-default').default

const getStoreState = (stores) => {
  return Object.keys(stores).reduce((result, storeName) => {
    result[storeName] = stores[storeName].toJson()
    return result
  }, {})
}

module.exports = (bundle, template, req, res) => {
  return new Promise((resolve, reject) => {
    const createStoreMap = bundle.createStoreMap
    const createApp = bundle.default

    const routerContext = {}
    const stores = createStoreMap()
    const sheetsRegistry = new SheetsRegistry()
    const jss = createJss(preset())
    const app = createApp(stores, routerContext, sheetsRegistry, jss, req.url)

    asyncBootstrap(app).then(() => {
      if (routerContext.url) {
        res.status(302).setHeader('Location', routerContext.url)
        res.end()
        return
      }
      const helmet = Helmet.rewind()
      const state = getStoreState(stores)
      const content = ReactDomServer.renderToString(app)

      console.log(sheetsRegistry.toString())
      const html = ejs.render(template, {
        appString: content,
        initialState: serialize(state),
        meta: helmet.meta.toString(),
        title: helmet.title.toString(),
        style: helmet.style.toString(),
        link: helmet.link.toString(),
        materialCss: sheetsRegistry.toString(),
      })
      res.send(html)
      resolve()
    }).catch(reject)
  })
}

and my enrty is here:

import React from 'react'
import { StaticRouter } from 'react-router-dom'
import { Provider, useStaticRendering } from 'mobx-react'

import { JssProvider } from 'react-jss'
import { MuiThemeProvider, createMuiTheme } from 'material-ui/styles'
import { lightBlue, pink } from 'material-ui/colors'
import createGenerateClassName from 'material-ui/styles/createGenerateClassName'

import App from './views/App'
import { createStoreMap } from './store/store'

// 让mobx在服务端渲染的时候不会重复数据变换

useStaticRendering(true)

const theme = createMuiTheme({
  palette: {
    primary: pink,
    accent: lightBlue,
    type: 'light',
  },
})

export default (stores, routerContext, sheetsRegistry, jss, url) => {
  jss.options.createGenerateClassName = createGenerateClassName
  return (
    <Provider {...stores}>
      <StaticRouter context={routerContext} location={url}>
        <JssProvider registry={sheetsRegistry} jss={jss}>
          <MuiThemeProvider theme={theme}>
            <App />
          </MuiThemeProvider>
        </JssProvider>
      </StaticRouter>
    </Provider>
  )
}

export { createStoreMap }

@hesamd I am so sorry, I also don't know where is the problem.

@WenXuanYuan I have fixed this warning! )) You just need to use jss from react-jss/lib/jss

// import { create, SheetsRegistry } from 'jss';
// import preset from 'jss-preset-default';
import { createMuiTheme } from 'material-ui/styles';
import { purple, green } from 'material-ui/colors';
import createGenerateClassName from 'material-ui/styles/createGenerateClassName';
import  jss, { SheetsRegistry } from 'react-jss/lib/jss';

const theme = createMuiTheme({
    palette: {
        primary: purple,
        secondary: green,
    },
});

// console.log(jss, _jss);
// Configure JSS
// const jss = create(preset());
jss.options.createGenerateClassName = createGenerateClassName;

export const sheetsManager = new Map();

export default function createContext() {
    return {
        jss,
        theme,
        // This is needed in order to deduplicate the injection of CSS in the page.
        sheetsManager,
        // This is needed in order to inject the critical CSS.
        sheetsRegistry: new SheetsRegistry(),
    };
}

@modelfak
what about preset() ?
your fix removes the warning but it's not working as expected

@modelfak :+1:

@modelfak did you resolve the preset issue? Gary

I'm having the same issue right now, following the create-react-app demo.

@aislanmaia Thanks for raising. It should be fixed with e485be3b268e1692824543274cf4289127fde871.

@oliviertassinari in your first comment, you mentionned moving jss to peerDependencies. This would totally make sense sine we might want to use a different version in our application.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

TimoRuetten picture TimoRuetten  ·  3Comments

newoga picture newoga  ·  3Comments

revskill10 picture revskill10  ·  3Comments

sys13 picture sys13  ·  3Comments

finaiized picture finaiized  ·  3Comments