What is the alternative of makeStyles for Material UI v.5
Asked Answered
R

9

39

I just started using Material UI version 5. Originally to use my custom theme's styles, I would use makestyles, but it seems that does not work in v.5. My themes are on their own component, and to import those, I used {createTheme} instead of the old {createMuiTheme}. I have my theme imported into the Parent component as usual and have it set up as <ThemeProvider theme{theme}></ThemeProvider>.

Now, on my other component, I again was trying to use useStyles, but it was not working because it is not used in version 5. I am having a hard time trying to figure out how to convert it so that it can be used in version 5. Here is some of the unfinished code I was working on:

const useStyles = makeStyles((theme) => ({
    logo: {
        height: "8em",
        marginLeft: "0.2em",
    },
    tabContainer: {
        marginLeft: "auto",
    },
    tab: {
        ...theme.typography.tab,
        minWidth: 10,
        marginRight: "50px",
        opacity: 1,
        "&hover": {
            color: theme.palette.common.purple,
            textDecoration:"none",
        },
    },
}));

export default function Navigation(props) {
    const classes = useStyles();

    const [value, setValue] = useState(0);

    const handleChange = (e, value) => {
        setValue(value);
    };
    const refreshPage = () => {
        window.location.reload();
    };
    
    useEffect(() => {
        switch (window.location.pathname) {
            case "/":
                if (value !== 0) {
                    setValue(0);
                }
                break;
                default:
                break;
        }
    }, [value]);


    return (
      <React.Fragment>
        <ElevationScroll>
          <AppBar
            position="relative"
            style={{
              borderBottom: "2px solid black",
            }}
          >
            <Toolbar disableGutters>
                <img src={logo} alt="nasa logo" className={classes.logo}/>
                <Typography variant="h1" style={{ textAlign: "center" }}>
                  Nasa<br></br>Photos
                </Typography>
                <Tabs
                  value={value}
                  onChange={handleChange}
                  className={classes.tabContainer}
                  indicatorColor="primary"
                >
                  <Tab
                    className={classes.tab}
                    component={Link}
                    onClick={refreshPage}
                    to="/"
                    label="Home"
                  />
                </Tabs>
            </Toolbar>
          </AppBar>
        </ElevationScroll>
      </React.Fragment>
    );
}

I have read about the xs property and I have also heard of the styled() through Material UI's documentation, but I am having a hard time applying it to the code that I have written and would like a push in the right direction.

So to edit what I had earlier, I am going to also add my Theme.js file as well. I thought that this has been done correctly, but again it isn't reading my tab nor my palette.

import {createTheme} from "@mui/material/styles";

const pink = "#FFC0CB";
const lightblue = "#ADD8E6";
const purple = "#800080";
const black = "#000000";

const theme = createTheme({
    palette: {
        common: {
            pink: pink,
            lightblue: lightblue,
            purple: purple,
            black: black
        },
        primary: {
            main: pink,
            mainGradient: "linear-gradient(to left, purple, pink)",
        },
        secondary: {
            main: lightblue,
            mainGradient: "linear-gradient(to right, lightblue, pink)"
        },
    },
    typography: {
        tab: {
            fontFamily:"Orbitron",
            textTransform: "none",
            fontSize: "2.5rem",
            color: black,
        },
        h1: {
            fontFamily: "Orbitron",
            fontSize: "2.5em"
        },
        h2: {
            fontFamily: "Orbitron",
            fontSize: "2.5em"
        },
        subtitle1: {
            fontFamily: "Orbitron"
        },
        subtitle2: {
            fontFamily: "Orbitron",
            fontSize: "1.5rem"
        },
        buttons: {
            fontFamily: "Orbitron",
            textTransform: "none"
        },
    },
});

export default theme

I have imported my theme into my App.js file which is my top level file, I will include that here just in case something has been done wrong with that:

import React,{useState} from "react";
import PicOfDay from "./Components/PictureOfDay";
import Navigation from "./Components/Navigation";
import {
  Typography,
} from "@mui/material";
import {ThemeProvider} from '@mui/material/styles'
import theme from "../src/ui/Theme";
import {BrowserRouter as Router} from "react-router-dom";

function App(props) {
  const [date, setDate] = useState(new Date());
  return (
    <ThemeProvider theme={theme}>
      <Router>
        <Navigation date={date} setDate={setDate} />
        <Typography
          variant="h1"
          style={{fontSize: "5rem", textAlign: "center", marginTop:"2rem"}}
          >
            Astronomy Picture of the Day
        </Typography>  
        {/* <PicOfDay date={date} /> */}
      </Router>
    </ThemeProvider>
  );
}

export default App;

I did look at some documentation a couple of you sent me, and I was looking at the troubleshooting part where it said "[Types] Property "palette", "spacing" does not exist on type 'DefaultTheme'" because makeStyles is exported differently and it does not know about Theme. There seems to be a snipet to put in a typescript project (which I am not running, I am using javascript) and there was a section to add a ts file to my javascript and put the snippet it recommended, which I tried, but am I missing something because it did not do anything and I am not sure if I need to put something in my App.js file in order for it to read that?

Repressive answered 21/9, 2021 at 4:29 Comment(0)
O
13

You can still use the makeStyles utils as what you're using, but in material v5 if you love to do it you need to install one more package @mui/styles and

import { makeStyles } from '@mui/styles';

https://mui.com/guides/migration-v4/#mui-material-styles

The makeStyles JSS utility is no longer exported from @mui/material/styles. You can use @mui/styles/makeStyles instead.

Also, you need to add tab and purple to createTheme if you need them

const theme = createTheme({
  typography: {
    tab: {
      fontSize: 20,
    },
  },
  palette: {
    common: {
      purple: 'purple',
    },
  },
})
Oid answered 21/9, 2021 at 12:55 Comment(6)
I checked and I already had @mui/styles installed. I have makestyles imported as: import {makeStyles} from "@mui/styles" and it still is not working. I notice in my vs code when hoovering over my spread of ...theme.typography.tab and color: theme.palette.common.purple it says (parameter) theme: DefaultTheme, when it used to in v.4 say (paramter) theme: ThemeRepressive
yes, that true, in v5 the theme has the type is DefaultTheme instead of on Theme as v4 >Since makeStyles is now exported from @mui/styles package which does not know about Theme in the core package. mui.com/guides/migration-v4/… In your case you need to add tab and purple to createTheme ` const theme = createTheme({ typography: { tab: { fontSize: 20, }, }, palette: { common: { purple: 'purple', }, }, }) `Oid
I've added more to my original postRepressive
Ok one important thing when doing this kind of migration you need to have the StyledEngineProvider with the injectFirst option at the top of your component tree mui.com/guides/migration-v4/#style-libraryOid
That did it! When I used<StyledEngineProvider injectFirst> it fixed my issues with the styles not working. I just realized I had a typo in one of my makestyles, I spelled typography wrong. After realizing that, it worked. Besides that, I am just having a weird issue where my first Tab is not being displayed. If I have a second tab, the 2nd tab shows, but the first one still doesn't display. I think it's probably better to ask that as another question. Can you put that in your answer as wellRepressive
@mui/styles is the legacy styling solution for MUI. It is deprecated in v5.Depute
D
12

Based on documentation:

@mui/styles is the legacy styling solution for MUI. It is deprecated in v5. It depends on JSS as a styling solution, which is not used in the @mui/material anymore.

You can use the-sx-prop or styled

Depute answered 7/12, 2021 at 15:39 Comment(0)
G
2

@mui/styles is not compatible with React.StrictMode or React 18.

it's recommanded to use the sx props

import * as React from 'react';
import { Box } from '@mui/system';

export default function BasicUsage() {
  return (
    <Box
      component= 'div'
      sx={{
        color: 'darkslategray',
        backgroundColor: 'aliceblue',
        padding: 8,
        borderRadius: 4,
      }}
    >
      Styled div
    </Box>
  );
}

or

you can use styled() function from @mui/system package or @mui/material/styles package, if no theme be created, the difference is in the default theme used in these packages.

import * as React from 'react'; 
import { styled } from '@mui/system';
     
const MyComponent = styled('div')({   
  color: 'darkslategray',  
  backgroundColor: 'aliceblue',   
  padding: 8,   
  borderRadius: 4, 
});
     
export default function BasicUsage() {   
  return <MyComponent>Styled div</MyComponent>;
}
Gerena answered 27/2, 2023 at 15:56 Comment(0)
O
1
import * as React from 'react';
import { StyledEngineProvider } from '@mui/material/styles';

export default function GlobalCssPriority() {
  return (
    <StyledEngineProvider injectFirst>
      {/* Your component tree. Now you can override MUI's styles. */}
    </StyledEngineProvider>
  );
}

You need to use provider on main file to get default styles first.
Visit here Material UI injections!

Ogdon answered 26/7, 2022 at 16:12 Comment(0)
J
0

Assuming that you need to use the theme in your styles, This:

const useStyles = makeStyles((theme) => (
 root : {
   background: theme.palette.primary.main,
 }));

Becomes this:

import { SxProps, Theme, useTheme } from "@mui/material/styles";

const useStyles = (theme: Theme): { [key: string]: SxProps } => ({
   root : {
     background: theme.palette.primary.main,
   }
})
Jochbed answered 9/11, 2023 at 16:30 Comment(0)
J
0

I made a near drop-in replacement without having to install any libraries. You may need to tweak a few things like padding, margin, and border-radius to be px values. Also, follow patterns using the new SX prop to override existing styles. This sped up our transition greatly.

https://gist.github.com/jottenlips/c96b3023f8512ba49edab440d3326b17

// typescript
import { SxProps } from '@mui/material'
import { useMemo } from 'react'

type TStylesFunction = (
  props?: any,
) => Record<string, React.CSSProperties | SxProps>
type TStyles = Record<string, React.CSSProperties | SxProps>

export const makeStylesHook = (styles: TStylesFunction | TStyles) => {
  // useStyles returned like deprecated MUI makeStyles
  const useStyles =
    typeof styles === 'function'
      ? (props?: any) => {
          return useMemo(() => styles(props), [props])
        }
      : (_props?: any) => {
          return useMemo(() => styles, [])
        }
  return useStyles
}
  
// use
// const useStyles = makeStylesHook((props) => ({ box: { backgroundColor: "green"}}))
//...
// const Component = () => { 
//   const classes = useStyles()
//   return <Box sx={classes.box} />
// }
Jowl answered 22/3, 2024 at 15:7 Comment(0)
I
0

an example of how to create theme using mui v5.. I am 2 yrs late to answer this lolz... Was facing similar issue so found this method... leaving it here for someone else :)

import { makeStyles,createTheme, ThemeProvider, StyledEngineProvider } from '@mui/material/styles';

const theme = createTheme({
    palette: {
        mode: 'light',
        primary: {
            main: '#004586',
        },
        secondary: {
            main: '#99002A',
        },
    },
    props: {
        MuiOutlinedInput: {},
    },
});

const useStyles = makeStyles((theme) => ({
    root: {
        '& .MuiTypography-h4 ': {
            paddingLeft: '6px !important',
        },
        '& .MuiTypography-h5 ': {
            paddingLeft: '6px !important',
        },
        '& .MuiTextField-root': {
            margin: theme.spacing(1),
        },
        '& .MuiFormControl-root': {
            margin: theme.spacing(1),
            marginTop: theme.spacing(1),
            minWidth: '275px',
            maxWidth: '275px',
        },
        '& .MuiTableCell-head': {
            fontWeight: '700',
        },
        '& .MuiFormControl-fullWidth': {
            maxWidth: '100% !important',
        },

        '& .small-input.MuiFormControl-root': {
            minWidth: '100px',
            width: '100px',
        },
        '& .small-input.MuiFormControl-root input': {
            textAlign: 'center',
        },
        '& .med-input.MuiFormControl-root': {
            minWidth: '125px',
            width: '125px',
        },
        '& .med-input.MuiFormControl-root input': {
            textAlign: 'center',
        },
        '& .small-label.MuiFormControl-root': {
            minWidth: '90px',
            width: '90px',
        },
        '& .small-label.MuiFormControl-root input': {
            textAlign: 'center',
            paddingLeft: 0,
            paddingRight: 0,
        },
        '& .med-label.MuiFormControl-root': {
            minWidth: '110px',
            width: '110px',
        },
        '& .med-label.MuiFormControl-root input': {
            textAlign: 'center',
            paddingLeft: 0,
            paddingRight: 0,
        },
        '& .small-select.MuiFormControl-root': {
            minWidth: '150px',
            width: '150px',
        },
        '& .med-select.MuiFormControl-root': {
            minWidth: '225px',
            width: '225px',
        },
        '& .MuiTypography-h5': {
            marginTop: theme.spacing(2),
            color: '#004586',
        },
        '& .MuiTypography-h4': {
            marginTop: theme.spacing(2),
            color: '#004586',
        },
        '& .MuiInputLabel-formControl': {
            backgroundColor: '#FAFAFA',
            paddingLeft: '8px',
            paddingRight: '8px',
        },
        '& .MuiPaper-root .MuiInputLabel-formControl': {
            backgroundColor: '#FFFFFF',
            paddingLeft: '8px',
            paddingRight: '8px',
        },
        '& .MuiTypography-root': {
            padding: '10px',
            paddingLeft: '16px',
            paddingRight: '16px',
        },
        '& .MuiDivider-root': {
            marginTop: '20px',
        },
        '& .MuiOutlinedInput-root.Mui-disabled .MuiOutlinedInput-notchedOutline': {
            border: 'none',
        },
        '& .MuiInputBase-input.Mui-disabled': {
            color: 'rgba(0, 0, 0, 0.87)',
        },
        '& .MuiButtonBase-root': {
            cursor: 'pointer !important',
        },
    },
}));
Incommutable answered 15/4, 2024 at 20:20 Comment(0)
L
0

You can use the recommended sx or the styled API from @mui/system. But if you like separating CSS similar to the "old" makeStyles, you can use Typescript Record type which will still give CSS typing. Here is an example:

const classes: Record<string, React.CSSProperties> = {
    modal: {
      display: 'flex',
      padding: 1,
      alignItems: 'center',
      justifyContent: 'center',
    },
    paper: {
      width: 700,
      backgroundColor: 'white',
      borderRadius: '10px',
      padding: '15px 20px',
      display: 'flex',
      flexDirection: 'column',
      justifyContent: 'center',
      alignItems: 'center',
      textAlign: 'center',
    },
  };

Then you can use it in your component like so:

<Modal
      open={open}
      onClose={handleClose}
      aria-labelledby="parent-modal-title"
      aria-describedby="parent-modal-description"
      sx={classes.modal}
    >
      <Box sx={classes.paper}>
        <p>Hello world </p>
      </Box>
    </Modal>
Loyce answered 8/7, 2024 at 20:23 Comment(0)
B
-1

so what i understood from this question is that you want to add custom classes to the material-ui components. and makestyles is giving you error about theme.. you can resolve this by providing default theme to makestyles. you can use ThemeProvider to do that.. all you've to do is create a default theme with createTheme() then use that in ThemeProvider to pass it to all components in tree below ThemeProvider.. just use ThemeProvider to wrap your root component and that will provide default theme to each makeStyles that are currently in use..

import { makeStyles } from '@mui/styles';
import { createTheme, ThemeProvider } from '@mui/material/styles';

const theme = createTheme();

 const useStyles = makeStyles((theme) => (
 root : {
   background: theme.palette.primary.main,
 }));

 function Component() {
   const classes = useStyles();
   return <div className={classes.root} />
 }

 // In the root of your app
 function App(props) {

 return <ThemeProvider theme={theme}><Component {...props} /></ThemeProvider>;
 }
Bootie answered 24/1, 2022 at 3:17 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.