React: CssBaseLine component doesn't update after Material UI theme changed - reactjs

I wanted to update CssBaseline component whenever the theme was changed by button, but it didn't.
Whenever button is clicked, theme seemed to be changed, but what CssBaseline did hasn't been changed such as body's background color, etc.
Is there any way to change it?
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App/>
</React.StrictMode>,
document.getElementById('root')
);
App.js
import React, { useState, useEffect } from 'react';
import './App.css';
import { Button, Container } from '#material-ui/core';
import Title from './components/Title';
import { lightTheme, darkTheme } from './libs/Theme';
import { MuiThemeProvider, CssBaseline } from '#material-ui/core';
function App() {
const [theme, setTheme] = useState(darkTheme);
const handleClick = () => {
theme.palette.type === 'dark' ? setTheme(lightTheme) : setTheme(darkTheme);
}
return (
<MuiThemeProvider theme={theme}>
<CssBaseline />
<Button variant="contained" color="primary" onClick={handleClick}>Change Theme</Button>
<Container maxWidth="xl">
<Title />
</Container>
</MuiThemeProvider>
);
}
export default App;
libs/Theme.js
import { createMuiTheme, responsiveFontSizes } from '#material-ui/core';
export const lightTheme = responsiveFontSizes(
createMuiTheme({
palette: {
type: 'light'
}
})
);
export const darkTheme = responsiveFontSizes(
createMuiTheme({
palette: {
type: 'dark'
}
})
);

This is probably the work of <React.StrictMode>. Take those tags out and it should work. You can track this issue: https://github.com/mui-org/material-ui/issues/20708 for the bug and its possible resolution.
Note that this answer was written on MUI latest release v4.11.0

Related

override component mui v5 react

I'm using mui v5 and I'm trying to override the Container component to be have a padding of 4rem.
here is a simple code example:
import * as React from "react";
import { Container } from "#mui/material";
import Navbar from "./components/Navbar";
import { styled } from "#mui/system";
import CssBaseline from "#mui/material/CssBaseline";
import { ThemeProvider, StyledEngineProvider } from "#mui/material/styles";
import theme from "./theme";
const MyContainer = styled(Container, {})`
padding-left: 4rem;
background-color: aqua;
`;
export default function App() {
return (
<ThemeProvider theme={theme}>
<StyledEngineProvider injectFirst>
<CssBaseline />
<MyContainer maxWidth="xl">
<div>test</div>
</MyContainer>
</StyledEngineProvider>
</ThemeProvider>,
);
}
But this yields no results.
here is a sandbox:
https://codesandbox.io/s/wizardly-leakey-xumyd
You can use make use of shouldForwardProp of mui v5.
const MyContainer = styled(Container, {
shouldForwardProp: (prop) => prop
})(({ padding }) => ({
padding: padding,
backgroundColor: "aqua"
}));
You can check forked codesandbox here
open this

Cannot find name 'classes'. TS2304?

I want to customize my appbar size on react Mui(currently using v4, but I get an error everytime I try to create a style.
My current Code
import React from "react";
import { AppBar, Toolbar, Typography, Box, makeStyles } from '#material-ui/core';
import { Link } from "react-router-dom";
import './Navbar.css'
const styles ={
customizeToolbar: {
minHeight: 36
}
};
function Navbar(){
return(
<AppBar position='sticky' >
<Toolbar variant='dense' style={classes.customizeToolbar} >
</Toolbar>
</AppBar>
)
}
export default Navbar;
import React from "react";
import { AppBar, Toolbar, Typography, Box, makeStyles } from '#material-ui/core';
import { Link } from "react-router-dom";
import './Navbar.css'
const styles ={
customizeToolbar: {
minHeight: 36
}
};
function Navbar(){
return(
<AppBar position='sticky' >
<Toolbar variant='dense' style={styles.customizeToolbar} >
</Toolbar>
</AppBar>
)
}
export default Navbar;
If you wish to customize the theme, you need to use the ThemeProvider component in order to inject a theme into your application. You must create styles with makeStyles, then you can create variable classes and use it in jsx with className not style. If you want customize not only Navbar but all components you can set ThemeProvider in index.js
import { createTheme, ThemeProvider } from '#mui/material/styles';
import { createStyles, makeStyles } from '#mui/styles';
const useStyles = makeStyles(() =>
createStyles({
customizeToolbar: {
minHeight: 36
}
})
);
const theme = createTheme();
function Navbar(){
const classes = useStyles();
return(
<ThemeProvider theme={theme}>
<AppBar position='sticky' >
<Toolbar variant='dense' className={classes.customizeToolbar} >
</Toolbar>
</AppBar>
</ThemeProvider>
)
}

Why is the custom palette ignored in MUI?

Using MUI 4.12 and I have set the type to dark and used CssBaseline which was the solution I have seen for other answers but still it seems the type is completely ignored.
import {React, Fragment} from 'react'
import {
createTheme,
ThemeProvider,
makeStyles,
Zoom,
Fab,
useScrollTrigger,
Box,
CircularProgress
} from "#material-ui/core";
import CssBaseline from '#mui/material/CssBaseline';
import KeyboardArrowUpIcon from "#material-ui/icons/KeyboardArrowUp";
import "./App.css";
import Footer from "./Components/Footer/footer";
import { AppRouter } from "./Router/Router";
const theme = createTheme({
palette: {
type: "dark",
primary: {
main: "#d32f2f",
},
secondary: {
main: "#ef5350",
},
inherit: {
main: "white",
},
},
overrides : {
MuiTab : {
textColorInherit : {
opacity :1,
}
}
}
});
function App(props) {
return (
<Fragment>
<div className="App">
<Box id="back-to-top-anchor" />
<ThemeProvider theme={theme}>
<CssBaseline/>
<AppRouter />
<ScrollTop {...props}>
<Fab color="primary" size="small" aria-label="scroll back to top">
<KeyboardArrowUpIcon />
</Fab>
</ScrollTop>
</ThemeProvider>
</div>
<Footer />
</Fragment>
);
}
You're importing CssBaseline from #mui/material which is the package for MUI v5. In v5, MUI uses emotion instead of JSS (different style library internally), so your code doesn't work. You need to import the components from the same version to fix the problem:
V5
import { createTheme, ThemeProvider, CssBaseline, ... } from '#mui/material';
V4
import { createTheme, ThemeProvider, CssBaseline, ... } from '#material-ui/core';
Related answer
Material UI Dark Mode

Material-UI ThemeProvider not passing theme to components

I've created a theme in my App.js which overrides the Primary and Secondary color. I have ThemeProvider wrapping a Home component. The overridden values are not showing up in the Home component. What am I doing wrong?
App.js
import React from 'react'
import { ThemeProvider, createMuiTheme } from '#material-ui/core/styles'
import purple from '#material-ui/core/colors/purple'
import green from '#material-ui/core/colors/green'
import Home from './components/Home'
const theme = createMuiTheme({
overrides: {
pallete: {
primary: {
main: purple[500]
},
secondary: {
main: green[500]
}
}
}
})
const App = () => {
return (
<ThemeProvider theme={theme}>
<Home />
</ThemeProvider>
)
}
export default App
Home.js
import React from 'react'
import { useTheme } from '#material-ui/core/styles'
import { Container, Grid, AppBar, Toolbar, CssBaseline } from '#material-ui/core'
const Home = () => {
const theme = useTheme()
return (
<Container max="lg">
<CssBaseline />
<Grid container>
<Grid item xs={12}>
<AppBar color="primary">
<Toolbar>
Hello World
</Toolbar>
</AppBar>
</Grid>
</Grid >
</Container >
)
}
export default Home
I would think that in my AppBar the color="primary" should show up with the overridden primary color. But it's not happening.
You've got some typo (like pallete instead of palette, redundant overrides prop etc).
Here a working example.

What is best practice of 'ThemeProvider' in styled-components?

I wanna know where <ThemeProvider/> should be placed in React app.
I'd come up with two solutions about it.
1, <ThemeProvider/> should be used 'Just Once' in top-root component
like index.js or App.js file created by 'create-react-app' tool.
2, <ThemeProvicer/> should be placed in 'Each root of React-component'
literally.
for clarification, I'll show you some example.
there is just two component, 'Red' and 'Blue' <div> tag.
1, <ThemeProvider/> used 'Just Once'
// In './red.js'
import React from 'react'
import styled from "styled-components"
const Red = styled.div`background: ${props => props.theme.mainColor}`
export default function RedDiv() {
return (
//NOT using ThemeProvider
<Red />
)
}
// In './blue.js'
......
const Blue = styled.div`background: ${props => props.theme.subColor}`
export default function BlueDiv() {
return (
<Blue />
)
}
// In './App.js'
import React, { Component } from 'react'
import { ThemeProvider } from "styled-components"
import myTheme from "./myTheme
import Red from "./red"
import Blue from "./blue"
export default class App extends Component {
render() {
return (
//only used here just once
<ThemeProvider theme={myTheme}>
<>
<Red />
<Blue />
</>
</ThemeProvider>
)
}
}
2, <ThemeProvider/> used 'Each root of React-component'
// In './red.js'
import React from 'react'
import styled, { ThemeProvider } from "styled-components"
const Red = styled.div`background: ${props => props.theme.mainColor} `
export default function RedDiv() {
return (
<ThemeProvider theme={myTheme}>
<Red />
</ThemeProvider>
)
}
// In './blue.js'
......
const Blue = styled.div`background: ${props => props.theme.mainColor}`
export default function BlueDiv() {
return (
<ThemeProvider theme={myTheme}>
<Blue />
</ThemeProvider>
)
}
// In './App.js'
import React, { Component } from 'react'
import Red from "./red"
import Blue from "./blue"
export default class App extends Component {
render() {
return (
<>
// <ThemeProvider/> is not used
<Red />
<Blue />
</>
)
}
}
there is maybe some typo on the code above, but I hope that this example will convey my idea clearly.
I use it only once, inside index.js.
Also a good place to add some global styles, if you need them. I use them for resetCSS (http://meyerweb.com/eric/tools/css/reset/) and some baseCSS rules like box-sizing etc.
index.js
import { createGlobalStyle, ThemeProvider } from 'styled-components';
import theme from './styles/theme';
import resetCSS from './styles/resetCSS';
import baseCSS from './styles/baseCSS';
import { BrowserRouter as Router} from "react-router-dom";
const GlobalStyle = createGlobalStyle`
${resetCSS}
${baseCSS}
`;
React.DOM.render(
<React.Fragment>
<GlobalStyle/>
<Router>
<ThemeProvider theme={theme}>
<App/>
</ThemeProvider>
</Router>
</React.Fragment>
,document.getElementById('root')
);

Resources