Material UI V5 : makeStyles not working in material ui V5 - reactjs

I was trying to upgrate material v5(from v4). As per documentation , it is recommended to use
Styled or sx API but I wanted to use makeStyles approach as in v4. Even though it is deprecated in v5 but can be used(as per documentation). But I am unable to get theme variable inside makeStyles callback function causing cann't access property of undefined(eg. theme.breakpoints.between...)
import makeStyles from '#mui/styles/makeStyles';
const useStyles = makeStyles((theme) => ({
// here theme variable is undefined
appBar: {
backgroundColor: "white",
height: "60px",
padding: "0px 5em",
[theme.breakpoints.between("xs", 'lg')]: {
padding: "0px",
},
},
.......
Here is my index.js
import { ThemeProvider, StyledEngineProvider } from "#mui/material/styles";
import theme from "./theme/theme"
ReactDOM.render(
<React.StrictMode>
<StyledEngineProvider injectFirst>
<ThemeProvider theme={theme}>
<CssBaseline />
<App />
</ThemeProvider>
</StyledEngineProvider>
</React.StrictMode>,
document.getElementById("root")
);
theme.js
import { createTheme, responsiveFontSizes, adaptV4Theme } from "#mui/material/styles";
import baseTheme from "./baseTheme";
let theme = createTheme(adaptV4Theme(baseTheme));
theme = responsiveFontSizes(theme);
export default theme;
Also I noticed, StyledEngineProvider is not being property imported(followed this)
package.json
"#emotion/react": "^11.5.0",
"#emotion/styled": "^11.3.0",
"#fortawesome/fontawesome-svg-core": "^1.2.32",
"#fortawesome/free-solid-svg-icons": "^5.15.1",
"#fortawesome/react-fontawesome": "^0.1.13",
"#mui/icons-material": "^5.1.0",
"#mui/lab": "^5.0.0-alpha.54",
"#mui/material": "^5.1.0",
"#mui/styles": "^5.1.0",
Do I have to install additional package to make it working?

Okay, just had this problem. The makeStyles and styled uses a different context to get theme. In order for your makeStyles to access the theme you need import { ThemeProvider } from '#mui/styles'. But to use styled(), you need import { ThemeProvider } from '#mui/material'.
And if you use both styled() AND makeStyles for migration, you need to have BOTH of those theme providers....

Related

Theme not being provided to sub-components using makeStyles MUI v5 [duplicate]

I'm studying MUI, and in the course, the instructor asks me to style just one component and not the entire theme.
For that, it uses the makeStyles function and spreads the theme.mixins.toolbar. The problem is when I do this, I have the following error:
TypeError: Cannot read properties of undefined (reading 'toolbar')
This course is apparently in version 4, and I am using version 5. Despite this, my code appears to follow the changes that the documentations asks for. So what could be causing this error?
app.js
import "./App.css";
import Header from "./components/ui/Header";
import { ThemeProvider } from "#material-ui/core/styles";
import theme from "./components/ui/Theme";
function App() {
return (
<ThemeProvider theme={theme}>
<Header />
</ThemeProvider>
);
}
export default App;
Theme.js
import { createTheme } from "#material-ui/core/styles";
const arcBlue = "#0B72B9";
const arcOrange = "#FFBA60";
export default createTheme({
typography: {
h3: {
fontWeight: 100,
},
},
palette: {
common: {
blue: `${arcBlue}`,
orange: `${arcOrange}`,
},
primary: {
main: `${arcBlue}`,
},
secondary: {
main: `${arcOrange}`,
},
},
});
header/index.jsx
import React from "react";
import AppBar from "#mui/material/AppBar";
import Toolbar from "#mui/material/Toolbar";
import useScrollTrigger from "#mui/material/useScrollTrigger";
import Typography from "#mui/material/Typography";
import { makeStyles } from "#material-ui/styles";
function ElevationScroll(props) {
const { children, window } = props;
const trigger = useScrollTrigger({
disableHysteresis: true,
threshold: 0,
target: window ? window() : undefined,
});
return React.cloneElement(children, {
elevation: trigger ? 10 : 0,
});
}
const useStyles = makeStyles((theme) => ({
toolbarMargin: { ...theme.mixins.toolbar },
}));
function Header() {
const classes = useStyles();
return (
<React.Fragment>
<ElevationScroll>
<AppBar color="primary">
<Toolbar>
<Typography variant="h3" component="h3">
Nome de teste
</Typography>
</Toolbar>
</AppBar>
</ElevationScroll>
<div className={classes.toolBarMargin} />
</React.Fragment>
);
}
export default Header;
Since you're using v5, change your ThemeProvider, createTheme and makeStyles import path from:
import { ThemeProvider, createTheme, makeStyles } from "#material-ui/core/styles";
To:
import { ThemeProvider, createTheme } from "#mui/material/styles";
import { makeStyles } from "#mui/styles";
#material-ui/core is v4 package and #mui/material is the v5 equivalent. The API from the 2 versions are not compatible. In v5, makeStyles is also moved to a legacy package called #mui/styles, if you are using MUI v5 in a new project, you should switch completely to styled/sx API as recommended by the MUI team.
Related answers
Difference between #mui/material/styles and #mui/styles?
Cannot use palette colors from MUI theme
MUI createTheme is not properly passing theme to MUI components
I created a project on CodeSandbox and it doesn't seem the problem in code.
I guess you need to check the version of package you installed in package.json file.
Here is the link to the CodeSandbox project and you can see the console.log message on console tab.
https://codesandbox.io/s/check-makestyle-eq67m?file=/src/components/ui/Header/index.js
I faced similar issue with Can not read properties of undefined, reading refs thrown by makeStyles. In my case it was mui v5 and the issue occurred after upgrading to React 18.
In my case it turned out I had some legacy makeStyles(()=>createStyles) wrapped in a manner:
const useStyles = (minWidth: number) =>
makeStyles((theme: Theme) => ...
I had to change it to:
const useStyles =
makeStyles((theme: Theme) => ...
Perhaps it will be useful for somebody else facing the issue.
Solution
Install #mui/styles
npm install #mui/styles
Change
import { ThemeProvider, createTheme } from "#material-ui/core/styles";
To
import { ThemeProvider, createTheme } from "#mui/material/styles";
And
import { makeStyles } from "#material-ui/styles";
To
import { makeStyles } from "#mui/styles";
And
<div className={classes.toolBarMargin} />
To
<div className={classes.toolbarMargin} />

how to prevent a material-ui package from overriding my app style?

I am using the latest Material-UI installation in a React-Gatsby app.
I installed a third party package for a carousel (react-material-ui-carousel).
When I use this package I see it overrides some of my material-ui styles by adding css divs that compete with my app's css divs.
the data-emotion divs are added by my app, and the data-jss style divs are added by the package react-material-ui-carousel.
Is there a way to limit the carousel styling only to the carousel component and not impact the other material-ui components on my page?
(for example the MuiButtonBase contains the MuiButtonBase-root rules that override my site's rules)
try to check your package-lock
and use 3 blocs
"node_modules/react-material-ui-carousel": {
"version": "2.3.7-mui5",
"resolved": "https://registry.npmjs.org/react-material-ui-carousel/-/react-material-ui-carousel-2.3.7-mui5.tgz",
"integrity": "sha512-XM6+kn6db++riBKUufl7XQI8eE/qj5XWpkDpHUWnioICCdUqx6cvWJmIqjBqcMNB4FgcgJFVmsE3iEKs/4gRIA==",
"dependencies": {
"auto-bind": "^2.1.1",
"react-swipeable": "^6.1.0"
},
"peerDependencies": {
"#emotion/react": "^11.4.1",
"#emotion/styled": "^11.3.0",
"#mui/icons-material": "^5.0.0",
"#mui/material": "^5.0.0",
"#mui/styles": "^5.0.0",
"react": "^17.0.1",
"react-dom": "^17.0.1"
}
},
"react-material-ui-carousel": {
"version": "2.3.7-mui5",
"resolved": "https://registry.npmjs.org/react-material-ui-carousel/-/react-material-ui-carousel-2.3.7-mui5.tgz",
"integrity": "sha512-XM6+kn6db++riBKUufl7XQI8eE/qj5XWpkDpHUWnioICCdUqx6cvWJmIqjBqcMNB4FgcgJFVmsE3iEKs/4gRIA==",
"requires": {
"auto-bind": "^2.1.1",
"react-swipeable": "^6.1.0"
}
},
"react-material-ui-carousel": "^2.3.7-mui5",
You can use StylesProvider from #material-ui/core/styles with this you can put prefix to classes names and avoid styles override
import {
MuiThemeProvider,
ThemeProvider,
StylesProvider,
createGenerateClassName,
} from '#material-ui/core/styles';
const generateClassName = createGenerateClassName({
seed: 'classes-custom-prefix',
});
export const Provider = ({ children, theme }) => {
return (
<StylesProvider generateClassName={generateClassName}>
<MuiThemeProvider theme={theme}>
<ThemeProvider theme={theme}>{children}</ThemeProvider>
</MuiThemeProvider>
</StylesProvider>
);
};
I was having issues/inconsistencies with styles between production and deploy. For me, the best way to style elements and override MUI styles without "!important" is using:
import { styled } from "#mui/material/styles";
import Button from "#material-ui/core/Button";
const CustomButton = styled(Button)(({ theme }) => ({
display: "flex",
...
}));
And then instead of using
<Button ...args>label</Button>
use
<CustomButton ...args>label</CustomButton>

Material UI custom styles do not apply on the component

I have just started learning Material UI in react js.
When it comes to custom styling, I encounter an issue where everything seems to be logically correct but the styling doesn't apply.
There is a button in Create.js component which I'm trying to change its style with the help of import { makeStyles } from "#material-ui/styles"
These are the dependencies installed in package.json:
"dependencies": {
"#emotion/react": "^11.4.1",
"#emotion/styled": "^11.3.0",
"#material-ui/styles": "^4.11.4",
"#mui/icons-material": "^5.0.1",
"#mui/material": "^5.0.2",
Here is Create.js component:
import React from "react";
import Typography from "#mui/material/Typography";
import { Button, Container } from "#mui/material";
import KeyboardArrowRightIcon from "#mui/icons-material/KeyboardArrowRight";
import { makeStyles } from "#material-ui/styles";
const useStyle = makeStyles({
btn: {
fontSize: 60,
backgroundColor: "red",
},
});
export default function Create() {
const classes = useStyle();
return (
<Container>
<Typography
variant="h6"
color="textSecondary"
align="center"
gutterBottom
>
Create a New Note
</Typography>
<Button
className={classes.btn}
onClick={() => console.log("you clicked me")}
type="submit"
color="secondary"
variant="contained"
endIcon={<KeyboardArrowRightIcon />}
>
Submit
</Button>
</Container>
);
}
This is what I see when I inspect the element:
DevTools keeps ignoring this style
The code is so far good. One difference I observed in documentation and the provided code is the import of makeStyles. Try importing makesStyles from #mui/styles. For reference have a look at documentation.
Also MUI is now compatible with plain css for minor tweaks like these. Please refer here
As far as the issue of browser ignoring styles is concerned a workaround can be using important keyword in custom styles but that is not a recommended and inefficient way.

ThemeProvider does not apply theme to child components from material ui library

I am using Typescript, React. Material-UI (now MUI) and Webpack.
I am trying to apply a theme using material-ui's ThemeProvider but it only seems to apply that theme to components that are not from the material-ui library.
import React from 'react'
import { ThemeProvider, CssBaseline } from '#material-ui/core'
import { createTheme } from '#material-ui/core/styles'
import Router from './components/Router'
import NavBar from './components/NavBar'
import Toolbar from '#mui/material/Toolbar'
import Container from '#mui/material/Container'
export function App(): JSX.Element {
const theme = createTheme({
palette: {
type: 'dark',
primary: {
main: '#ffeb3b',
},
secondary: {
main: '#795548',
},
},
})
return (
<ThemeProvider theme={theme}>
<NavBar />
<Toolbar />
<Container>
<Router />
</Container>
<CssBaseline />
</ThemeProvider>
)
}
The I can see darkmode being toggled so long as the backdrop for the app is not a MUI paper element. Also my AppBar contained within my NavBar component does not change color when I change the palette main colors.
Putting the theme into a different file does not help. And I have already run Yarn upgrade so everything should be up to date. What is going on?

Why is ThemeProvider generating this error?

So I am a bit new to react and I am trying to set up a toggled theme for my website.
These are the instructions I followed -"https://css-tricks.com/a-dark-mode-toggle-with-react-and-themeprovider/"
Note: My app is a react + NetCore app.
Whenever I use the ThemeProvider this is the error I get:
"Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem."
Here is my App.js code:
import React, { Component } from 'react';
import { Route } from 'react-router';
import { Layout } from './components/Layout';
import { Home } from './components/Home';
import { ThemeProvider } from 'styled-components';
import { GlobalStyles } from './components/GlobalTheme'
import { LightTheme, DarkTheme } from './components/Themes';
export default class App extends Component {
displayName = App.name
render() {
return (
<ThemeProvider theme={DarkTheme}>
<div>
<GlobalStyles />
<Layout>
<Route exact path='/' component={Home} />
</Layout>
</div>
</ThemeProvider>
)}
}
Here is my package.json file:
{
"name": "NotePadApp",
"version": "0.1.0",
"private": true,
"dependencies": {
"bootstrap": "^3.4.1",
"react": "17.0.2",
"react-redux": "^6.0.0",
"react-bootstrap": "^0.31.5",
"react-dom": "17.0.2",
"react-router-bootstrap": "^0.24.4",
"react-router-dom": "5.2.0",
"react-scripts": "1.0.17",
"rimraf": "^2.6.2"
},
"scripts": {
"start": "rimraf ./build && react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
Here is GlobalStyle:
//Global Themes
import { createGlobalStyle } from 'styled-components';
export const GlobalStyles = createGlobalStyle`
*,
*:: after,
*:: before {
box - sizing: border - box;
}
body {
background: ${({ theme }) => theme.bodyBackGroundColor} !important;
color: ${({ theme }) => theme.textColor} !important;
}
`;
Here is themes.js:
//Themes
export const DarkTheme = {
bodyBackGroundColor: '#222222',
textColor: '#ffffff',
}
export const LightTheme = {
bodyBackGroundColor: '#ffffff',
textColor: '#222222',
}
These are the suggestions given to me and I have looked into them as best as I could with no luck.
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
The problem is that you are passing JSON in ThemeProvider's theme prop but you should pass createMuiTheme. So your code becomes:
import React, { Component } from 'react';
import { Route } from 'react-router';
import { Layout } from './components/Layout';
import { Home } from './components/Home';
import { ThemeProvider, createMuiTheme } from '#material-ui/core/styles'; //<-- import createMuiTheme
import { GlobalStyles } from './components/GlobalTheme'
import { LightTheme, DarkTheme } from './components/Themes';
export default class App extends Component {
displayName = App.name
const theme = createMuiTheme(DarkTheme); //<-- here create mui theme calling createMuiTheme with DarkTheme JSON
render() {
return (
<ThemeProvider theme={theme}> //<-- pass theme to ThemeProvider
<div>
<GlobalStyles />
<Layout>
<Route exact path='/' component={Home} />
</Layout>
</div>
</ThemeProvider>
)}
}

Resources