7
votes

I'm learning React with TypeScript and using the Material UI framework for the frontend. I try to get the media queries working, but I got an error:

Uncaught TypeError: Cannot read property 'up' of undefined at styles (webpack-internal:///./app/components/navigation/Toolbar/index.tsx:59)

This is the corresponding code:

const styles = ({breakpoints}: Theme) => createStyles( {
    grow: {
        flexGrow: 1
    },
    menuButton: {
        marginLeft: -12,
        marginRight: 20
    },
    sectionDesktop: {
        display: 'none',
        [breakpoints.up('md')]: {
            display: 'flex'
        }
    },
    sectionMobile: {
        display: 'flex'
    },
})

The styles are passed to the component with:

export default withStyles(styles)(Toolbar)

I read that it is not required to create a custom theme as the default one will be passed automatically to the functions. However, the breakpoints property of theme is undefined which cause a blank page.

Thanks for your help

Edit

Here is the code of the component which will still produce the problem without any other components.

import * as React from 'react'
import {
    Theme
} from '@material-ui/core'
import {
    createStyles,
    WithStyles,
    withStyles
} from '@material-ui/styles'
// import Drawer from '../Drawer'

const styles = ({breakpoints}: Theme) => createStyles( {
    grow: {
        flexGrow: 1
    },
    menuButton: {
        marginLeft: -12,
        marginRight: 20
    },
    sectionDesktop: {
        display: 'none',
        [breakpoints.up('md')]: {
            display: 'flex'
        }
    },
    sectionMobile: {
        display: 'flex'
    },
})

namespace Toolbar {
    interface Props {
    }

    export interface State {
        isOpen : boolean
        mobileMoreAnchorEl? : EventTarget & HTMLElement
    }

    export type AllProps = Props & WithStyles<typeof styles>
}

class Toolbar extends React.Component<Toolbar.AllProps, Toolbar.State> {
    constructor(props: Toolbar.AllProps, context?: any) {
        super(props, context);
        this.state = { isOpen: false, mobileMoreAnchorEl: undefined}
    }

    render() {
        const { classes } = this.props
        // const { isOpen } = this.state

        return(
            <React.Fragment>
                <div className={classes.sectionDesktop}>
                    Hello
                </div>
                <div className={classes.sectionMobile}>
                    World
                </div>
            </React.Fragment>
        )
    }

}

export default withStyles(styles)(Toolbar)

The main.tsx (a.k.a index.js) looks like this:

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createBrowserHistory } from 'history';
import { configureStore } from 'app/store';
import { Router } from 'react-router';
import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles';
import { App } from './app';

// prepare store
const history = createBrowserHistory()
const store = configureStore()
const theme = createMuiTheme()

ReactDOM.render(
  <Provider store={store}>
    <Router history={history}>
      <MuiThemeProvider theme={theme} >
        <App />
      </MuiThemeProvider>
    </Router>
  </Provider>,
  document.getElementById('root')
);

So, adding MuiThemeProvider does not help.

1
Please show the full code of the simplest form of your Toolbar component that still reproduces the problem. There is something of significance that you aren't showing here because this works fine for me here without typescript and here using typescript.Ryan Cogswell
I removed most of the code from the component, but the problem still occurs. I compared your code with mine and can't see any relevant differences.Denis Loh

1 Answers

24
votes

UPDATE

At the time when this answer was first written, @material-ui/styles was unstable. It is not anymore (as of v4), but it is still generally best to import from @material-ui/core/styles since the default theme will not be available when importing from @material-ui/styles.


You can read here that @material-ui/styles is unstable (alpha version).

You'll notice in my CodeSandbox that I am using:

import { withStyles, createStyles } from "@material-ui/core/styles";

instead of importing these from @material-ui/styles. When I use the same import as you, I am able to reproduce your problem.

Edit 82kp602xqj


UPDATE for v5

In v5, usage of makeStyles and withStyles is deprecated and they were removed from @material-ui/core and are only accessible via @material-ui/styles. In v5, makeStyles and withStyles do not have access to the theme unless you provide access via the ThemeProvider (and for that to work you should be using the latest v5 versions of both @material-ui/core and @material-ui/styles). Below is a working v5 example.

import React from "react";
import ReactDOM from "react-dom";
import { createTheme, ThemeProvider } from "@material-ui/core/styles";
import { withStyles } from "@material-ui/styles";
const styles = ({ breakpoints }) => ({
  grow: {
    flexGrow: 1
  },
  menuButton: {
    marginLeft: -12,
    marginRight: 20
  },
  sectionDesktop: {
    display: "none",
    [breakpoints.up("md")]: {
      display: "flex"
    }
  },
  sectionMobile: {
    display: "flex"
  }
});
const MyToolbar = (props) => {
  return (
    <>
      <div className={props.classes.sectionDesktop}>Section Desktop</div>
      {props.children}
      <div className={props.classes.sectionMobile}>Section Mobile</div>
    </>
  );
};
const theme = createTheme();
const StyledToolbar = withStyles(styles)(MyToolbar);
function App() {
  return (
    <ThemeProvider theme={theme}>
      <StyledToolbar>
        <div>Hello</div>
        <div>CodeSandbox</div>
      </StyledToolbar>
    </ThemeProvider>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Edit v5 withStyles