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.
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.
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With