Chakra UI theme not rendering - reactjs

I have followed the documentation of chakra UI and am trying to style my website. For some reason the config part for the dark/light mode works but the theme part does not work.
I have used create-react-app
This is my Index.js code-
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { AuthProvider } from './Contexts/AuthProvider';
import { ChakraProvider, theme } from '#chakra-ui/react'
import defaultTheme from "./Themes/stylesEntryPoint"
import { ColorModeScript } from '#chakra-ui/react'
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<ChakraProvider theme={defaultTheme}>
<AuthProvider>
<ColorModeScript initialColorMode={theme.config.initialColorMode} />
<App />
</AuthProvider>
</ChakraProvider>
);
This is the code for stylesEntryPoint file
import { extendTheme } from '#chakra-ui/react'
import {theme,config} from "./FoundationTheme/globalStyles"
const defaultTheme = {
theme , config
}
export default extendTheme(defaultTheme)
This is the code for globalStyles... I have copied it from chakra UI documentation here https://chakra-ui.com/docs/styled-system/global-styles
import { mode } from '#chakra-ui/theme-tools'
import { extendTheme } from '#chakra-ui/react'
export const config = {
initialColorMode: 'dark',
useSystemColorMode: true
}
export const theme = {
styles: {
global: (props) => ({
'html, body': {
fontSize: 'lg',
color: props.colorMode === 'dark' ? 'pink.100' : 'gray.600',
lineHeight: 'tall',
},
a: {
color: props.colorMode === 'dark' ? 'teal.300' : 'teal.500',
},
}),
},
}

Related

cannot use custom Material UI theme [duplicate]

I'm trying something very simple: building two themes for a website using Material-UI themes:
A light theme and dark one, but it does not work well: the theme is on every Material-UI react element, but the root element on the html document keeps having the same default white background.
Of course it can be changed by attacking the body with pure .css:
body {
background-color: #222;
}
But I was looking to change it dynamically with React, I though this would work, but it does not:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { ThemeProvider } from '#material-ui/styles';
import { MuiThemeProvider, createMuiTheme } from '#material-ui/core/styles';
const themeLight = createMuiTheme({
palette: {
background: {
default: "#e4f0e2"
}
},
});
const themeDark = createMuiTheme({
palette: {
background: {
default: "#222222",
}
},
});
ReactDOM.render(
<MuiThemeProvider theme = { themeDark }>
<App />
</MuiThemeProvider>, document.getElementById('root'));
and I'm lost here, there is no way to make this with Material-UI theme?
CssBaseline is the component that controls this aspect. If you aren't using CssBaseline, then you are just seeing the default provided by the browser.
Here is a working v4 example (v5 example further down):
import React from "react";
import ReactDOM from "react-dom";
import CssBaseline from "#material-ui/core/CssBaseline";
import { MuiThemeProvider, createMuiTheme } from "#material-ui/core/styles";
import Button from "#material-ui/core/Button";
const themeLight = createMuiTheme({
palette: {
background: {
default: "#e4f0e2"
}
}
});
const themeDark = createMuiTheme({
palette: {
background: {
default: "#222222"
},
text: {
primary: "#ffffff"
}
}
});
const App = () => {
const [light, setLight] = React.useState(true);
return (
<MuiThemeProvider theme={light ? themeLight : themeDark}>
<CssBaseline />
<Button onClick={() => setLight(prev => !prev)}>Toggle Theme</Button>
</MuiThemeProvider>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Below is a Material-UI v5 example. The only difference from v4 is the name change for ThemeProvider (though this name is also available in v4 in addition to MuiThemeProvider) and createTheme (instead of createMuiTheme) and using the new #mui/material package name instead of #material-ui/core.
import React from "react";
import ReactDOM from "react-dom";
import CssBaseline from "#mui/material/CssBaseline";
import { ThemeProvider, createTheme } from "#mui/material/styles";
import Button from "#mui/material/Button";
const themeLight = createTheme({
palette: {
background: {
default: "#e4f0e2"
}
}
});
const themeDark = createTheme({
palette: {
background: {
default: "#222222"
},
text: {
primary: "#ffffff"
}
}
});
const App = () => {
const [light, setLight] = React.useState(true);
return (
<ThemeProvider theme={light ? themeLight : themeDark}>
<CssBaseline />
<Button onClick={() => setLight((prev) => !prev)}>Toggle Theme</Button>
</ThemeProvider>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
In MUI v5, you can also use GlobalStyles component to add the styles to the body element:
<GlobalStyles
styles={{
body: { backgroundColor: "lightyellow" }
}}
/>
On top of #NearHuscarl 's answer, importing the GlobalStyles after the CSSBaseLine, will retain the page defaults (like margin: 0, etc.,) still able to customize root-level / global styles. For eg,
import { Component } from "react";
import { Button, CssBaseline, GlobalStyles } from "#mui/material";
import { ThemeProvider, createTheme } from "#mui/material/styles";
export class App extends Component {
render() {
const theme = createTheme({
palette: {
mode: "dark",
primary: {
main: "#ff0000",
contrastText: "#fff",
},
secondary: {
main: green[500],
},
},
});
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<GlobalStyles
styles={{
body: { backgroundColor: "cyan" },
}}
/>
<Button color="primary" variant="contained">
Button
</Button>
</ThemeProvider>
);
}
}
export default App;
(I'm just using class component out of habit 😅)
Full example with nested themes MUI Theme toggle
My use case, I only wanted to change background-color of body from within a React component, not the entire theme. Used a global override.
TL;DR code:
// other imports ...
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles((theme) => ({
'#global':{
body:{
backgroundColor:"#382E7E"
}
},
otherstyles:{
// other styles ....
},
}));
// React component, etc ...
MUI Version 5
import { createTheme } from "#mui/material/styles";
const themeX = createMuiTheme({
palette: {
mode: "dark",
}
});
MUI Version 4
import { createMuiTheme } from '#material-ui/core/styles';
const themeX = createMuiTheme({
palette: {
type: "dark",
}
});
just as simple that, changing the pallets type to dark by default its set to light. This will also help in custom color for other components like typography, icon etc
ReactDOM doesn't replace the targeted element. I haven't worked with material ui personally. However, if you put the background color you want into your App state as something like 'currentRootColor', then in your App component's render function you could put:
render() {
document.body.style.backgroundColor = this.state.currentRootColor;
...the rest of your App render code
}
This would set the body's background color and if you change 'this.state.currentRootColor', then your App component would re-render with the new background color.
However if you dont already have a < body > tag in your document you would need to add one.
In MUI v5, this seem to work for me. I used it to apply specific styles only to HomePage (overwrite default styles).
pages/HomePage.js
...
import GlobalStyles from '#mui/material/GlobalStyles';
// or
import { GlobalStyles } from '#mui/material';
Note: It is a good practice to hoist the <GlobalStyles /> to a static
constant, to avoid rerendering. This will ensure that the tag
generated would not recalculate on each render.
const homePageStyles = (
<GlobalStyles
styles={{
body: { backgroundColor: 'cyan' },
'.MuiTypography-root': {
color: 'red',
},
}}
/>
);
...
return (
<>
{homePageStyles}
<MyComponents />
</>
);
....
More:
https://mui.com/material-ui/customization/how-to-customize/
https://mui.com/material-ui/api/global-styles/
All the above answers did not work for me, why?? I don't know.
I covered all of my components with ScopedCssBaseline and mui will apply the palette style only to the children.
Below is my answer,
import React from "react";
import ReactDOM from "react-dom";
import { ScopedCssBaseline, Button } from "#mui/material";
import { ThemeProvider, createTheme } from "#mui/material/styles";
const themeLight = createTheme({
palette: {
background: {
default: "#fff"
},
text: {
default: "#000"
}
}
});
const themeDark = createTheme({
palette: {
background: {
default: "#000"
},
text: {
primary: "#fff"
}
}
});
const App = () => {
const [light, setLight] = React.useState(true);
return (
<ThemeProvider theme={light ? themeLight : themeDark}>
<ScopedCssBaseline enableColorScheme>
<Button onClick={() => setLight((prev) => !prev)}>Toggle Theme</Button>
</ScopedCssBaseline>
</ThemeProvider>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

How to theme Material UI inside Storybook

Currently this is what I am doing, passing a ThemeProvider above my component file:
import React from 'react';
import { ThemeProvider, createMuiTheme } from '#material-ui/core/styles';
import MUIButton from '#material-ui/core/Button';
const theme = createMuiTheme({
palette: {
primary: {
main: "#ff0000"
}
},
typography: {
fontFamily: 'Nunito Sans, sans-serif',
button: {
textTransform: 'none'
}
},
shape: {
borderRadius: 3
}
})
export default ({ variant, children }) => {
return (
<ThemeProvider theme={theme}>
<MUIButton
color="primary"
variant={variant}
>
{children}
</MUIButton>
</ThemeProvider>
)
}
I am trying to figure out how I can do this at a global level in Storybook. This is the first component I have built out called Button. So I want to be able to have the theme in an external file, and have the ThemeProvider coming in at a higher level so I don't have to wrap each component. Hope that makes sense, and if anyone has any ideas.
First, I suggest you to move your theme into a separate file (such as src/stylesheet so you can access it from different files (your global App component and your storybook preview file).
// src/stylesheet.ts
import { createMuiTheme } from '#material-ui/core/styles';
export const muiTheme = createMuiTheme({
palette: {
primary: {
main: "#ff0000"
}
},
typography: {
fontFamily: 'Nunito Sans, sans-serif',
button: {
textTransform: 'none'
}
},
shape: {
borderRadius: 3
}
})
Then, you need to setup your storybook the same way you set up your react app. To do so, try to create a file called:
.storybook/preview.js and put this inside of it:
// .storybook/preview.js
import React from 'react';
import { addDecorator } from '#storybook/react';
import { ThemeProvider } from '#material-ui/core/styles';
import { muiTheme } from '../src/stylesheet';
addDecorator((story) => (
<ThemeProvider theme={muiTheme}>{story()}</ThemeProvider>
));
It will wrap all your stories inside of the ThemeProvider.
In your app, you can can also have a global App component which will encapsulate the whole app within the ThemeProvider
More help:
https://storybook.js.org/docs/basics/writing-stories/
This is the only solution that worked for me with MUI v5:
// .storybook/main.js
const path = require('path');
const toPath = (filePath) => path.join(process.cwd(), filePath);
module.exports = {
webpackFinal: async (config) => {
return {
...config,
resolve: {
...config.resolve,
alias: {
...config.resolve.alias,
'#emotion/core': toPath('node_modules/#emotion/react'),
'emotion-theming': toPath('node_modules/#emotion/react'),
},
},
};
},
};
// .storybook/preview.js
import { ThemeProvider, createTheme } from '#mui/material/styles';
import { ThemeProvider as Emotion10ThemeProvider } from 'emotion-theming';
const defaultTheme = createTheme(); // or your custom theme
const withThemeProvider = (Story, context) => {
return (
<Emotion10ThemeProvider theme={defaultTheme}>
<ThemeProvider theme={defaultTheme}>
<Story {...context} />
</ThemeProvider>
</Emotion10ThemeProvider>
);
};
export const decorators = [withThemeProvider];
// ...other storybook exports
It's from the MUI migration guide but it took me unnecessarily long to find so I want to share it here:
https://mui.com/guides/migration-v4/
For Storybook 6.3+ it should look like the following
Update preview.js with:
import React from 'react';
import { theme } from './src/theme'; // whereever you have defined your material ui theme
export const decorators = [
Story => (
<ThemeProvider theme={theme}>
<Story />
</ThemeProvider>
),
];
More details on how to decorate your stories here:
https://storybook.js.org/docs/react/writing-stories/decorators
And creating your theme for Material UI here:
https://material-ui.com/customization/theming/
This works for me with react-router and mui V5
my preview.js =>
import React from 'react';
import { addDecorator } from '#storybook/react';
import { MemoryRouter } from 'react-router';
import { ThemeProvider } from '#mui/material/styles';
import { ThemeProvider as Emotion10ThemeProvider } from 'emotion-theming';
import customTheme from '../src/theme/index';
addDecorator((story) => (
<Emotion10ThemeProvider theme={customTheme}>
<ThemeProvider theme={customTheme}>
<MemoryRouter initialEntries={['/']}>{story()}</MemoryRouter>
</ThemeProvider>
</Emotion10ThemeProvider>
));
export const parameters = {
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
};
I believe this is the most up to date answer... and the cleanest, updating path/to/your/Theme with your path
// .storybook/preview.js
import React from 'react';
import { ThemeProvider } from '#mui/system';
import { Theme } from 'path/to/your/Theme';
export const decorators = [
(Story) => (
<ThemeProvider theme={Theme}>
<Story />
</ThemeProvider>
),
];

Material UI: Dark theme not being applied

I'm using the Context API to store the theme value. The theme itself is created with <createMuiTheme> and passed down from <Layout> to children via <MuiThemeProvider> and <CssBaseline>. I can see the state change via React DevTools but the theme itself is not being applied - and I'm at loss as to why...
Here is codesandbox with a full example - warning: contains Samuel L. Ipsum. What follows is an abridged version.
Default and dark theme definitions:
// theme/dark.js
import { createMuiTheme } from "#material-ui/core/styles";
const theme = createMuiTheme({
typography: {
useNextVariants: true
},
palette: {
type: "dark"
}
});
export default theme;
// theme/default.js
import { createMuiTheme } from "#material-ui/core/styles";
const theme = createMuiTheme({
typography: {
useNextVariants: true
},
palette: {
type: "light"
}
});
export default theme;
Context:
// context/settings/SettingsContext.js
import React from "react";
export default React.createContext({
darkMode: false
});
// context/settings/SettingsProvider.js
import React, { useState } from "react";
import SettingsContext from "./SettingsContext";
const storage = {
getItem(key) {
if (localStorage) {
return localStorage.getItem(key);
}
},
setItem(key, value) {
if (localStorage) {
return localStorage.setItem(key, value);
}
}
};
const SettingsProvider = props => {
const [darkMode, setDarkMode] = useState(
storage.getItem("darkMode") === "true"
);
const onSetDarkMode = darkMode => {
setDarkMode(darkMode);
storage.setItem("darkMode", darkMode);
};
return (
<SettingsContext.Provider
value={{
darkMode,
onSetDarkMode
}}
>
{props.children}
</SettingsContext.Provider>
);
};
export default SettingsProvider;
index.js:
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
import App from "./containers/app";
import SettingsProvider from "./context/settings/SettingsProvider";
ReactDOM.render(
<BrowserRouter>
<SettingsProvider>
<App />
</SettingsProvider>
</BrowserRouter>,
document.getElementById("root")
app/index.js:
import React, { useState } from "react";
import { Switch, Route } from "react-router-dom";
import { default as home } from "../home/routes";
import Layout from "../layout";
const App = () => {
const [anchorEl, setAnchorEl] = useState(null);
return (
<div>
<Layout anchorEl={anchorEl} setAnchorEl={setAnchorEl}>
<Switch>
{home.map((route, index) => (
<Route
key={index}
path={route.path}
exact={route.exact}
render={route.render}
/>
))}
</Switch>
</Layout>
</div>
);
};
export default App;
And layout/index.js:
import React, { useContext } from "react";
import { MuiThemeProvider } from "#material-ui/core/styles";
import { makeStyles } from "#material-ui/core/styles";
import CssBaseline from "#material-ui/core/CssBaseline";
import defaultTheme from "../../themes/default";
import darkTheme from "../../themes/default";
import SettingsContext from "../../context/settings/SettingsContext";
import Header from "../../components/header/index";
const useStyles = makeStyles(theme => ({
toolbarMargin: {
...theme.mixins.toolbar
}
}));
const Layout = props => {
const classes = useStyles();
const context = useContext(SettingsContext);
const theme = context.darkMode ? darkTheme : defaultTheme;
const { children, anchorEl, setAnchorEl } = props;
return (
<MuiThemeProvider theme={theme}>
<CssBaseline />
<Header anchorEl={anchorEl} setAnchorEl={setAnchorEl} />
<main>
<div className={classes.toolbarMargin} />
{children}
</main>
</MuiThemeProvider>
);
};
export default Layout;
What did I miss?
You're importing the same theme twice. I'd suggest using named exports instead of defaults, it helps a lot with auto importing, as well as spotting mistakes like this.
// layout/index.js
import defaultTheme from "../../themes/default";
import darkTheme from "../../themes/default"; // should be "../../theme/dark"

Change root background color with Material-UI theme

I'm trying something very simple: building two themes for a website using Material-UI themes:
A light theme and dark one, but it does not work well: the theme is on every Material-UI react element, but the root element on the html document keeps having the same default white background.
Of course it can be changed by attacking the body with pure .css:
body {
background-color: #222;
}
But I was looking to change it dynamically with React, I though this would work, but it does not:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { ThemeProvider } from '#material-ui/styles';
import { MuiThemeProvider, createMuiTheme } from '#material-ui/core/styles';
const themeLight = createMuiTheme({
palette: {
background: {
default: "#e4f0e2"
}
},
});
const themeDark = createMuiTheme({
palette: {
background: {
default: "#222222",
}
},
});
ReactDOM.render(
<MuiThemeProvider theme = { themeDark }>
<App />
</MuiThemeProvider>, document.getElementById('root'));
and I'm lost here, there is no way to make this with Material-UI theme?
CssBaseline is the component that controls this aspect. If you aren't using CssBaseline, then you are just seeing the default provided by the browser.
Here is a working v4 example (v5 example further down):
import React from "react";
import ReactDOM from "react-dom";
import CssBaseline from "#material-ui/core/CssBaseline";
import { MuiThemeProvider, createMuiTheme } from "#material-ui/core/styles";
import Button from "#material-ui/core/Button";
const themeLight = createMuiTheme({
palette: {
background: {
default: "#e4f0e2"
}
}
});
const themeDark = createMuiTheme({
palette: {
background: {
default: "#222222"
},
text: {
primary: "#ffffff"
}
}
});
const App = () => {
const [light, setLight] = React.useState(true);
return (
<MuiThemeProvider theme={light ? themeLight : themeDark}>
<CssBaseline />
<Button onClick={() => setLight(prev => !prev)}>Toggle Theme</Button>
</MuiThemeProvider>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Below is a Material-UI v5 example. The only difference from v4 is the name change for ThemeProvider (though this name is also available in v4 in addition to MuiThemeProvider) and createTheme (instead of createMuiTheme) and using the new #mui/material package name instead of #material-ui/core.
import React from "react";
import ReactDOM from "react-dom";
import CssBaseline from "#mui/material/CssBaseline";
import { ThemeProvider, createTheme } from "#mui/material/styles";
import Button from "#mui/material/Button";
const themeLight = createTheme({
palette: {
background: {
default: "#e4f0e2"
}
}
});
const themeDark = createTheme({
palette: {
background: {
default: "#222222"
},
text: {
primary: "#ffffff"
}
}
});
const App = () => {
const [light, setLight] = React.useState(true);
return (
<ThemeProvider theme={light ? themeLight : themeDark}>
<CssBaseline />
<Button onClick={() => setLight((prev) => !prev)}>Toggle Theme</Button>
</ThemeProvider>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
In MUI v5, you can also use GlobalStyles component to add the styles to the body element:
<GlobalStyles
styles={{
body: { backgroundColor: "lightyellow" }
}}
/>
On top of #NearHuscarl 's answer, importing the GlobalStyles after the CSSBaseLine, will retain the page defaults (like margin: 0, etc.,) still able to customize root-level / global styles. For eg,
import { Component } from "react";
import { Button, CssBaseline, GlobalStyles } from "#mui/material";
import { ThemeProvider, createTheme } from "#mui/material/styles";
export class App extends Component {
render() {
const theme = createTheme({
palette: {
mode: "dark",
primary: {
main: "#ff0000",
contrastText: "#fff",
},
secondary: {
main: green[500],
},
},
});
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<GlobalStyles
styles={{
body: { backgroundColor: "cyan" },
}}
/>
<Button color="primary" variant="contained">
Button
</Button>
</ThemeProvider>
);
}
}
export default App;
(I'm just using class component out of habit 😅)
Full example with nested themes MUI Theme toggle
My use case, I only wanted to change background-color of body from within a React component, not the entire theme. Used a global override.
TL;DR code:
// other imports ...
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles((theme) => ({
'#global':{
body:{
backgroundColor:"#382E7E"
}
},
otherstyles:{
// other styles ....
},
}));
// React component, etc ...
MUI Version 5
import { createTheme } from "#mui/material/styles";
const themeX = createMuiTheme({
palette: {
mode: "dark",
}
});
MUI Version 4
import { createMuiTheme } from '#material-ui/core/styles';
const themeX = createMuiTheme({
palette: {
type: "dark",
}
});
just as simple that, changing the pallets type to dark by default its set to light. This will also help in custom color for other components like typography, icon etc
ReactDOM doesn't replace the targeted element. I haven't worked with material ui personally. However, if you put the background color you want into your App state as something like 'currentRootColor', then in your App component's render function you could put:
render() {
document.body.style.backgroundColor = this.state.currentRootColor;
...the rest of your App render code
}
This would set the body's background color and if you change 'this.state.currentRootColor', then your App component would re-render with the new background color.
However if you dont already have a < body > tag in your document you would need to add one.
In MUI v5, this seem to work for me. I used it to apply specific styles only to HomePage (overwrite default styles).
pages/HomePage.js
...
import GlobalStyles from '#mui/material/GlobalStyles';
// or
import { GlobalStyles } from '#mui/material';
Note: It is a good practice to hoist the <GlobalStyles /> to a static
constant, to avoid rerendering. This will ensure that the tag
generated would not recalculate on each render.
const homePageStyles = (
<GlobalStyles
styles={{
body: { backgroundColor: 'cyan' },
'.MuiTypography-root': {
color: 'red',
},
}}
/>
);
...
return (
<>
{homePageStyles}
<MyComponents />
</>
);
....
More:
https://mui.com/material-ui/customization/how-to-customize/
https://mui.com/material-ui/api/global-styles/
All the above answers did not work for me, why?? I don't know.
I covered all of my components with ScopedCssBaseline and mui will apply the palette style only to the children.
Below is my answer,
import React from "react";
import ReactDOM from "react-dom";
import { ScopedCssBaseline, Button } from "#mui/material";
import { ThemeProvider, createTheme } from "#mui/material/styles";
const themeLight = createTheme({
palette: {
background: {
default: "#fff"
},
text: {
default: "#000"
}
}
});
const themeDark = createTheme({
palette: {
background: {
default: "#000"
},
text: {
primary: "#fff"
}
}
});
const App = () => {
const [light, setLight] = React.useState(true);
return (
<ThemeProvider theme={light ? themeLight : themeDark}>
<ScopedCssBaseline enableColorScheme>
<Button onClick={() => setLight((prev) => !prev)}>Toggle Theme</Button>
</ScopedCssBaseline>
</ThemeProvider>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

React & Material-UI: Theme undefined in createStyles() with TypeScript

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);

Resources