Categories
React Answers

How to pass props to React Material UI styles?

Sometimes, we want to pass props to React Material UI styles.

In this article, we’ll look at how to pass props to React Material UI styles.

How to pass props to React Material UI styles?

To pass props to React Material UI styles, we can call the useStyle hook returned by makeStyles with the props object.

In makeStyles, we can set the style properties that takes the props as a parameter and return the value we want.

For instance, we write:

import React from "react";
import { makeStyles } from "@material-ui/core";

const useStyles = makeStyles({
  firstStyle: {
    backgroundColor: (props) => props.backgroundColor
  },
  secondStyle: {
    color: (props) => props.color
  }
});

const MyComponent = ({ children, ...props }) => {
  const { firstStyle, secondStyle } = useStyles(props);
  return <div className={`${firstStyle} ${secondStyle}`}>{children}</div>;
};

export default function App() {
  return (
    <MyComponent color="yellow" backgroundColor="purple">
      hello world
    </MyComponent>
  );
}

We call makeStyles with an object that has some class names as properties.

And we set the properties to objects with style properties set to functions that returns the prop value we want.

Next, we define the MyComponent component that gets the props and pass it into useStyles.

Then we set the className to the classes that are returned from useStyles.

Finally, we render MyComponent with color and backgroundColor to render the colors that we set.

They will end up as values in the object that we pass into makeStyles.

As a result, the box has a purple background and the color of the text is yellow.

Conclusion

To pass props to React Material UI styles, we can call the useStyle hook returned by makeStyles with the props object.

In makeStyles, we can set the style properties that takes the props as a parameter and return the value we want.

Categories
React Answers

How to make a dropdown menu open below the Appbar using React Material-UI?

Sometimes, we want to make a dropdown menu open below the Appbar using React Material-UI.

In this article, we’ll look at how to make a dropdown menu open below the Appbar using React Material-UI.

How to make a dropdown menu open below the Appbar using React Material-UI?

To make a dropdown menu open below the Appbar using React Material-UI, we set the Menu‘s getContentAnchorEl to null.

Then we set anchorOrigin and transformOrigin to objects to position the menu.

For instance, we write:

import React from "react";
import { alpha, makeStyles } from "@material-ui/core/styles";
import AppBar from "@material-ui/core/AppBar";
import Toolbar from "@material-ui/core/Toolbar";
import IconButton from "@material-ui/core/IconButton";
import Typography from "@material-ui/core/Typography";
import Badge from "@material-ui/core/Badge";
import MenuItem from "@material-ui/core/MenuItem";
import Menu from "@material-ui/core/Menu";
import MenuIcon from "@material-ui/icons/Menu";
import AccountCircle from "@material-ui/icons/AccountCircle";
import MailIcon from "@material-ui/icons/Mail";
import NotificationsIcon from "@material-ui/icons/Notifications";
import MoreIcon from "@material-ui/icons/MoreVert";

const useStyles = makeStyles((theme) => ({
  grow: {
    flexGrow: 1
  },
  menuButton: {
    marginRight: theme.spacing(2)
  },
  title: {
    display: "none",
    [theme.breakpoints.up("sm")]: {
      display: "block"
    }
  },
  search: {
    position: "relative",
    borderRadius: theme.shape.borderRadius,
    backgroundColor: alpha(theme.palette.common.white, 0.15),
    "&:hover": {
      backgroundColor: alpha(theme.palette.common.white, 0.25)
    },
    marginRight: theme.spacing(2),
    marginLeft: 0,
    width: "100%",
    [theme.breakpoints.up("sm")]: {
      marginLeft: theme.spacing(3),
      width: "auto"
    }
  },
  searchIcon: {
    padding: theme.spacing(0, 2),
    height: "100%",
    position: "absolute",
    pointerEvents: "none",
    display: "flex",
    alignItems: "center",
    justifyContent: "center"
  },
  inputRoot: {
    color: "inherit"
  },
  inputInput: {
    padding: theme.spacing(1, 1, 1, 0),
    // vertical padding + font size from searchIcon
    paddingLeft: `calc(1em + ${theme.spacing(4)}px)`,
    transition: theme.transitions.create("width"),
    width: "100%",
    [theme.breakpoints.up("md")]: {
      width: "20ch"
    }
  },
  sectionDesktop: {
    display: "none",
    [theme.breakpoints.up("md")]: {
      display: "flex"
    }
  },
  sectionMobile: {
    display: "flex",
    [theme.breakpoints.up("md")]: {
      display: "none"
    }
  }
}));

export default function App() {
  const classes = useStyles();
  const [, setAnchorEl] = React.useState(null);
  const [mobileMoreAnchorEl, setMobileMoreAnchorEl] = React.useState(null);

  const isMobileMenuOpen = Boolean(mobileMoreAnchorEl);

  const handleProfileMenuOpen = (event) => {
    setAnchorEl(event.currentTarget);
  };

  const handleMobileMenuClose = () => {
    setMobileMoreAnchorEl(null);
  };

  const handleMobileMenuOpen = (event) => {
    setMobileMoreAnchorEl(event.currentTarget);
  };

  const mobileMenuId = "primary-search-account-menu-mobile";
  const renderMobileMenu = (
    <Menu
      anchorEl={mobileMoreAnchorEl}
      id={mobileMenuId}
      keepMounted
      open={isMobileMenuOpen}
      onClose={handleMobileMenuClose}
      getContentAnchorEl={null}
      anchorOrigin={{ vertical: "bottom", horizontal: "center" }}
      transformOrigin={{ vertical: "top", horizontal: "center" }}
    >
      <MenuItem>
        <IconButton color="inherit">
          <Badge badgeContent={4} color="secondary">
            <MailIcon />
          </Badge>
        </IconButton>
        <p>Messages</p>
      </MenuItem>
      <MenuItem>
        <IconButton color="inherit">
          <Badge badgeContent={11} color="secondary">
            <NotificationsIcon />
          </Badge>
        </IconButton>
        <p>Notifications</p>
      </MenuItem>
      <MenuItem onClick={handleProfileMenuOpen}>
        <IconButton color="inherit">
          <AccountCircle />
        </IconButton>
        <p>Profile</p>
      </MenuItem>
    </Menu>
  );

  return (
    <div className={classes.grow}>
      <AppBar position="static">
        <Toolbar>
          <IconButton
            edge="start"
            className={classes.menuButton}
            color="inherit"
            aria-label="open drawer"
          >
            <MenuIcon />
          </IconButton>
          <Typography className={classes.title} variant="h6" noWrap>
            Material-UI
          </Typography>
          <div className={classes.grow} />
          <div className={classes.sectionMobile}>
            <IconButton onClick={handleMobileMenuOpen} color="inherit">
              <MoreIcon />
            </IconButton>
          </div>
        </Toolbar>
      </AppBar>
      {renderMobileMenu}
    </div>
  );
}

We call makeStyles to add some styles for the menu.

Then we call the useStyles hook which is returned by makeStyles to return the classes object.

Next, we define states and functions for handling the opening and closing of the menu.

To make the top right menu open below the app bar, we set getContentAnchorEl to null.

Then we set anchorOrigin to an object with the vertical property set to 'bottom' and horizontal set to 'center'.

And we set transformOrigin to an object that has the vertical property set to 'top' and horizontal set to 'center'

We assign the Menu component to renderMobileMenu and put it below AppBar.

Conclusion

To make a dropdown menu open below the Appbar using React Material-UI, we set the Menu‘s getContentAnchorEl to null.

Then we set anchorOrigin and transformOrigin to objects to position the menu.

Categories
React Answers

How to set min or max attributes on TextField with type number?

Sometimes, we want to set min or max attributes on TextField with type number.

In this article, we’ll look at how to set min or max attributes on TextField with type number.

How to set min or max attributes on TextField with type number?

To set min or max attributes on TextField with type number, we set the InputProps prop to an object that has the inputProps property which has the min and max properties.

For instance, we write:

import { TextField } from "material-ui";
import React, { useState } from "react";
import MuiThemeProvider from "material-ui/styles/MuiThemeProvider";

const min = -10;
const max = 10;

export default function App() {
  const [value, setValue] = useState(0);

  return (
    <MuiThemeProvider>
      <div>
        <TextField
          type="number"
          inputProps={{ min, max }}
          value={value}
          onChange={(e) => {
            if (e.target.value === "") {
              setValue(e.target.value);
              return;
            }
            const value = +e.target.value;
            if (value > max) {
              setValue(max);
            } else if (value < min) {
              setValue(min);
            } else {
              setValue(value);
            }
          }}
        />
      </div>
    </MuiThemeProvider>
  );
}

We set the onChange prop to a function that checks the input value, which is stored in e.target.value.

If e.target.value is an empty string, we call setValue to store the value so we can clear the input.

Otherwise, we convert e.target.value to a number with the + operator and assign the number to value.

If value is bigger than max, we call setValue with max to set value to max.

Similarly, we set value to min if value is less than min.

Otherwise, we call setValue with value to set the value state to value.

Also, we set the value prop to the value state so that we see the input value displayed in the text field.

Conclusion

To set min or max attributes on TextField with type number, we set the InputProps prop to an object that has the inputProps property which has the min and max properties.

Categories
React Answers

How to fix the “TypeError: Cannot read property ‘prepareStyles’ of undefined” error when developing React apps with Material UI?

Sometimes, we need to fix the "TypeError: Cannot read property ‘prepareStyles’ of undefined" error when developing React apps with Material UI.

In this article, we’ll look at how to fix the "TypeError: Cannot read property ‘prepareStyles’ of undefined" error when developing React apps with Material UI.

How to fix the "TypeError: Cannot read property ‘prepareStyles’ of undefined" error when developing React apps with Material UI?

To fix the "TypeError: Cannot read property ‘prepareStyles’ of undefined" error when developing React apps with Material UI, we should wrap our Material UI components with the MuiThemeProvider component.

For instance, we write:

import { TextField } from "material-ui";
import React from "react";
import MuiThemeProvider from "material-ui/styles/MuiThemeProvider";

export default function App() {
  return (
    <MuiThemeProvider>
      <div>
        <TextField
          onKeyPress={(e) => {
            if (e.key === "Enter") {
              console.log(e.target.value);
            }
          }}
        />
      </div>
    </MuiThemeProvider>
  );
}

to wrap the TextField with the MuiThemeProvider component.

This lets Material UI apply the styles provided by Material UI for the components inside the MuiThemeProvider component.

Conclusion

To fix the "TypeError: Cannot read property ‘prepareStyles’ of undefined" error when developing React apps with Material UI, we should wrap our Material UI components with the MuiThemeProvider component.

Categories
React Answers

How to get the Material UI TextField value when enter key is pressed in React?

Sometimes, we want to get the Material UI TextField value when enter key is pressed in React.

In this article, we’ll look at how to get the Material UI TextField value when enter key is pressed in React.

How to get the Material UI TextField value when enter key is pressed in React?

To get the Material UI TextField value when enter key is pressed in React, we can set the onKeyPress prop of the TextField to a function that checks which key is pressed.

Then we can run the code we want when the key we’re checking for is pressed.

For instance, we write:

import { TextField } from "material-ui";
import React from "react";
import MuiThemeProvider from "material-ui/styles/MuiThemeProvider";

export default function App() {
  return (
    <MuiThemeProvider>
      <div>
        <TextField
          onKeyPress={(e) => {
            if (e.key === "Enter") {
              console.log(e.target.value);
            }
          }}
        />
      </div>
    </MuiThemeProvider>
  );
}

We set onKeyPress to a function that checks if the enter key is pressed by comparing 'Enter' against e.key.

If that’s true, then we log the TextField‘s value, which is stored in e.target.value.

Conclusion

To get the Material UI TextField value when enter key is pressed in React, we can set the onKeyPress prop of the TextField to a function that checks which key is pressed.

Then we can run the code we want when the key we’re checking for is pressed.