Using Material UI in React
A comprehensive guide on how to use Material UI in React for building visually appealing and responsive user interfaces.
Introduction
What is Material UI?
Material UI is a popular, open-source library that provides React components that implement Google's Material Design. It's a collection of React components that follow Google's Material Design guidelines to ensure your app has a consistent look and feel. Material UI offers a wide range of pre-built components like buttons, text fields, cards, dialogs, and more, which can significantly speed up the development process.
Why Use Material UI in React?
Using Material UI in React applications brings several benefits:
- Consistency: It ensures that your app adheres to Material Design principles, providing a consistent user experience.
- Speed: You can quickly build out your UI with pre-built components, reducing development time.
- Accessibility: Material UI components are designed with accessibility in mind, helping you build inclusive applications.
- Customization: You can easily customize the look and feel of your app to match your brand guidelines.
Setting Up Material UI
Installation
Prerequisites
Before you begin, make sure you have Node.js and npm (Node Package Manager) installed on your machine. You can download and install them from the official Node.js website.
Step-by-Step Installation Guide
- Create a React App: If you haven't already created a React app, you can do so using Create React App.
npx create-react-app my-material-ui-app cd my-material-ui-app
- Install Material UI: Use npm or yarn to install Material UI and its dependencies.
or
npm install @mui/material @emotion/react @emotion/styled
yarn add @mui/material @emotion/react @emotion/styled
Basic Configuration
Theme Setup
Material UI uses a theming system that allows you to customize the look and feel of your app. Let's set up a basic theme.
- Create a Theme File: Create a
theme.js
(ortheme.ts
for TypeScript) file in thesrc
directory.// src/theme.js import { createTheme } from '@mui/material/styles'; const theme = createTheme({ palette: { primary: { main: '#1976d2', }, secondary: { main: '#dc004e', }, }, }); export default theme;
- Set Up Theme Provider: Wrap your application with the
ThemeProvider
to apply the theme globally.// src/index.js import React from 'react'; import ReactDOM from 'react-dom'; import { ThemeProvider } from '@mui/material/styles'; import theme from './theme'; import App from './App'; ReactDOM.render( <ThemeProvider theme={theme}> <App /> </ThemeProvider>, document.getElementById('root') );
Customization
You can customize the theme further by modifying the createTheme
function. For example, you can add typography styles, spacing, and more.
Core Components
Buttons
Buttons allow users to take actions, and Material UI provides several variations to choose from.
Basic Button
The simplest type of button.
// src/App.js
import React from 'react';
import Button from '@mui/material/Button';
function App() {
return (
<div>
<Button variant="text">Text</Button>
<Button variant="contained">Contained</Button>
<Button variant="outlined">Outlined</Button>
</div>
);
}
export default App;
The expected output will be three buttons: one text button, one contained button, and one outlined button.
Raised Button
Raised buttons are the default contained buttons and have a raised appearance.
<Button variant="contained">Raised Button</Button>
Floating Action Button
Floating Action Buttons (FABs) are circular buttons used to promote a primary action.
import Fab from '@mui/material/Fab';
import AddIcon from '@mui/icons-material/Add';
function App() {
return (
<div>
<Fab color="primary" aria-label="add">
<AddIcon />
</Fab>
</div>
);
}
Usage Examples
Buttons can be used to trigger actions like form submissions, route navigation, or more.
Text Fields
Text fields are used to enter and edit text.
Basic Text Field
A standard text field.
import TextField from '@mui/material/TextField';
function App() {
return (
<div>
<TextField label="Basic" variant="outlined" />
</div>
);
}
Multi-line Text Field
For entering longer text.
<TextField
label="Multiline"
multiline
rows={4}
variant="outlined"
/>
Decorated Text Field
Adding additional decorations like icons.
import InputAdornment from '@mui/material/InputAdornment';
import TextField from '@mui/material/TextField';
import AccountCircle from '@mui/icons-material/AccountCircle';
function App() {
return (
<div>
<TextField
label="With icon"
variant="outlined"
InputProps={{
startAdornment: (
<InputAdornment position="start">
<AccountCircle />
</InputAdornment>
),
}}
/>
</div>
);
}
Usage Examples
Text fields are commonly used in forms for user input.
Selects
Selects are a powerful way to let users choose one or more options.
Basic Select
A simple dropdown select.
import Select from '@mui/material/Select';
import MenuItem from '@mui/material/MenuItem';
function App() {
const [age, setAge] = React.useState('');
const handleChange = (event) => {
setAge(event.target.value);
};
return (
<div>
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
value={age}
label="Age"
onChange={handleChange}
>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</div>
);
}
Controlled Select
A select controlled by the state.
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
value={age}
label="Age"
onChange={handleChange}
>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
Grouped Select
Grouping items in the dropdown.
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
value={age}
label="Age"
onChange={handleChange}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<ListSubheader>Age</ListSubheader>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
Usage Examples
Selects are used in forms to provide a list of options for the user.
Cards
Cards contain content and actions about a single subject.
Basic Card
A simple card with some text.
import Card from '@mui/material/Card';
import CardContent from '@mui/material/CardContent';
import Typography from '@mui/material/Typography';
function App() {
return (
<Card>
<CardContent>
<Typography variant="h5" component="div">
Basic Card
</Typography>
<Typography variant="body2" color="text.secondary">
This is a basic card.
</Typography>
</CardContent>
</Card>
);
}
Media Card
A card with media content.
import Card from '@mui/material/Card';
import CardMedia from '@mui/material/CardMedia';
import CardContent from '@mui/material/CardContent';
import Typography from '@mui/material/Typography';
function App() {
return (
<Card sx={{ maxWidth: 345 }}>
<CardMedia
component="img"
height="140"
image="/static/images/cards/contemplative-reptile.jpg"
alt="green iguana"
/>
<CardContent>
<Typography gutterBottom variant="h5" component="div">
Lizard
</Typography>
<Typography variant="body2" color="text.secondary">
Lizards are a widespread group of squamate reptiles, with over 6,000 species, ranging across all continents except Antarctica
</Typography>
</CardContent>
</Card>
);
}
Custom Card
Customizing the card's appearance.
import Card from '@mui/material/Card';
import CardContent from '@mui/material/CardContent';
import Typography from '@mui/material/Typography';
function App() {
return (
<Card sx={{ minWidth: 275, backgroundColor: '#f5f5f5' }}>
<CardContent>
<Typography variant="h5" component="div">
Custom Card
</Typography>
<Typography variant="body2" color="text.secondary">
This card has a custom background color.
</Typography>
</CardContent>
</Card>
);
}
Usage Examples
Cards are used to group related data and actions, providing a clean and organized UI.
Advanced Components
Dialogs
Dialogs inform users about a task and can contain critical information, require decisions, or involve multiple tasks.
Basic Dialog
A simple dialog box.
import Button from '@mui/material/Button';
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogContentText from '@mui/material/DialogContentText';
import DialogTitle from '@mui/material/DialogTitle';
function App() {
const [open, setOpen] = React.useState(false);
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div>
<Button variant="outlined" onClick={handleClickOpen}>
Open Dialog
</Button>
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">
{"Use Google's location service?"}
</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description">
Let Google help apps determine location. This means sending anonymous location data to Google, even when no apps are running.
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Disagree</Button>
<Button onClick={handleClose} autoFocus>
Agree
</Button>
</DialogActions>
</Dialog>
</div>
);
}
Form Dialog
A dialog with a form.
import Button from '@mui/material/Button';
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogTitle from '@mui/material/DialogTitle';
import TextField from '@mui/material/TextField';
function App() {
const [open, setOpen] = React.useState(false);
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div>
<Button variant="outlined" onClick={handleClickOpen}>
Open Form Dialog
</Button>
<Dialog open={open} onClose={handleClose}>
<DialogTitle>Add New Item</DialogTitle>
<DialogContent>
<TextField
autoFocus
margin="dense"
id="name"
label="Name"
type="email"
fullWidth
variant="outlined"
/>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Cancel</Button>
<Button onClick={handleClose}>Add</Button>
</DialogActions>
</Dialog>
</div>
);
}
Nested Dialog
A dialog that opens another dialog.
// This example is straightforward and follows the previous examples with an additional dialog.
Usage Examples
Dialogs are useful for displaying additional information or options to the user without leaving the current view.
Snackbars
Snackbars provide brief messages about app processes to the user.
Top Center Snackbar
Displays a snackbar at the top center of the screen.
import Button from '@mui/material/Button';
import Snackbar from '@mui/material/Snackbar';
import MuiAlert from '@mui/material/Alert';
function Alert(props) {
return <MuiAlert elevation={6} variant="filled" {...props} />;
}
function App() {
const [open, setOpen] = React.useState(false);
const handleClick = () => {
setOpen(true);
};
const handleClose = (event, reason) => {
if (reason === 'clickaway') {
return;
}
setOpen(false);
};
return (
<div>
<Button variant="outlined" onClick={handleClick}>
Open Top Center Snackbar
</Button>
<Snackbar open={open} autoHideDuration={6000} onClose={handleClose} anchorOrigin={{ vertical: 'top', horizontal: 'center' }}>
<Alert onClose={handleClose} severity="success" sx={{ width: '100%' }}>
This is a top-center snackbar!
</Alert>
</Snackbar>
</div>
);
}
Bottom Right Snackbar
Displays a snackbar at the bottom right of the screen.
<Snackbar
open={open}
autoHideDuration={6000}
onClose={handleClose}
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
>
<Alert onClose={handleClose} severity="info" sx={{ width: '100%' }}>
This is a bottom-right snackbar!
</Alert>
</Snackbar>
Usage Examples
Snackbars are ideal for providing real-time feedback to users.
Tooltips
Tooltips display brief descriptive text when the user hovers over, focuses on, or taps an element.
Basic Tooltip
A simple tooltip.
import Tooltip from '@mui/material/Tooltip';
import Button from '@mui/material/Button';
function App() {
return (
<Tooltip title="Delete">
<Button>Button</Button>
</Tooltip>
);
}
Usage Examples
Tooltips enhance usability by providing additional context without cluttering the UI.
Menus
Menus provide a list of options for users to choose from.
Simple Menu
A basic menu.
import Menu from '@mui/material/Menu';
import MenuItem from '@mui/material/MenuItem';
import Button from '@mui/material/Button';
import { useState } from 'react';
function App() {
const [anchorEl, setAnchorEl] = useState(null);
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
return (
<div>
<Button onClick={handleClick}>Open Menu</Button>
<Menu
id="basic-menu"
anchorEl={anchorEl}
open={Boolean(anchorEl)}
onClose={handleClose}
MenuListProps={{
'aria-labelledby': 'basic-button',
}}
>
<MenuItem onClick={handleClose}>Profile</MenuItem>
<MenuItem onClick={handleClose}>My account</MenuItem>
<MenuItem onClick={handleClose}>Logout</MenuItem>
</Menu>
</div>
);
}
Menu List
A more complex menu with submenus.
<MenuList>
<MenuItem onClick={handleClose}>Profile</MenuItem>
<MenuItem onClick={handleClose}>My account</MenuItem>
<MenuItem onClick={handleClose}>Logout</MenuItem>
</MenuList>
Usage Examples
Menus are useful for navigating and selecting options.
Theming and Customization
Theming with Material UI
Material UI uses a theming system to ensure your app's design is consistent and customizable.
Creating a Theme
Define a theme with specific colors, typography, and spacing.
// src/theme.js
import { createTheme } from '@mui/material/styles';
const theme = createTheme({
palette: {
primary: {
main: '#556cd6',
},
secondary: {
main: '#19857b',
},
error: {
main: red.A400,
},
background: {
default: '#fff',
},
},
});
export default theme;
Applying Theme Globally
Apply the theme using ThemeProvider
in your application's root component.
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { ThemeProvider } from '@mui/material/styles';
import theme from './theme';
import App from './App';
ReactDOM.render(
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>,
document.getElementById('root')
);
Theme Customization
Customize your theme further by modifying the createTheme
function.
const theme = createTheme({
palette: {
primary: {
main: '#ff5722',
},
},
typography: {
fontFamily: [
'-apple-system',
'BlinkMacSystemFont',
'"Segoe UI"',
'Roboto',
'"Helvetica Neue"',
'Arial',
'sans-serif',
'"Apple Color Emoji"',
'"Segoe UI Emoji"',
'"Segoe UI Symbol"',
].join(','),
},
});
Customize Components
Override default styles and apply custom styles using themes.
Override Styles
Override default styles for specific components.
import { createTheme } from '@mui/material/styles';
const theme = createTheme({
components: {
MuiButton: {
styleOverrides: {
root: {
background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
border: 0,
borderRadius: 3,
boxShadow: '0 3px 5px 2px rgba(255, 105, 132, .3)',
color: 'white',
},
},
},
},
});
Styling with Theme
Use theme properties to style components dynamically.
import { styled } from '@mui/system';
const MyButton = styled(Button)(({ theme }) => ({
background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
border: 0,
borderRadius: 3,
boxShadow: `0 3px 5px 2px rgba(255, 105, 132, .3)`,
color: 'white',
height: 48,
padding: '0 30px',
}));
function App() {
return (
<div>
<MyButton>My Styled Button</MyButton>
</div>
);
}
Usage Examples
Customizing components helps match your app's style guide.
Integrations
Icons
Material UI provides a large collection of icons.
Installation
Install the Material Icons package.
npm install @mui/icons-material
Basic Icon Usage
Use icons easily in your components.
import StarIcon from '@mui/icons-material/Star';
import IconButton from '@mui/material/IconButton';
function App() {
return (
<div>
<IconButton aria-label="delete">
<StarIcon />
</IconButton>
</div>
);
}
Custom Icons
Add custom icons to your app.
import { SvgIcon } from '@mui/material';
const HomeIcon = () => (
<SvgIcon>
<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z" />
</SvgIcon>
);
function App() {
return (
<div>
<HomeIcon />
</div>
);
}
React Router
Integrate Material UI with React Router for routing.
Installation
Install React Router.
npm install react-router-dom
Basic Integration
Set up basic routing.
import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';
import Button from '@mui/material/Button';
function App() {
return (
<Router>
<div>
<Button component={Link} to="/home">
Home
</Button>
<Button component={Link} to="/about">
About
</Button>
<Routes>
<Route path="/home" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</div>
</Router>
);
}
Advanced Routing
Use advanced routing features for more complex navigation.
import { Routes, Route, Home, About, NotFound, useNavigate } from 'react-router-dom';
import Button from '@mui/material/Button';
function App() {
let navigate = useNavigate();
const handleButtonClick = () => {
navigate('/home');
};
return (
<div>
<Button onClick={handleButtonClick}>Go to Home</Button>
<Routes>
<Route path="/home" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="*" element={<NotFound />} />
</Routes>
</div>
);
}
Formik
Integrate Formik for form management.
Installation
Install Formik.
npm install formik
Basic Integration
Set up a basic form using Formik and Material UI.
import { Formik, Form, Field, ErrorMessage } from 'formik';
import { TextField } from '@mui/material';
function App() {
return (
<Formik
initialValues={{ name: '' }}
onSubmit={(values) => {
alert(JSON.stringify(values, null, 2));
}}
>
{({ handleSubmit }) => (
<Form onSubmit={handleSubmit}>
<Field
component={TextField}
name="name"
type="text"
label="Name"
fullWidth
margin="normal"
variant="outlined"
/>
<ErrorMessage name="name" component="div" />
<Button type="submit" variant="contained" color="primary">
Submit
</Button>
</Form>
)}
</Formik>
);
}
Validation
Add validation to your form fields.
import { Formik, Form, Field, ErrorMessage } from 'formik';
import * as Yup from 'yup';
import { TextField } from '@mui/material';
const validationSchema = Yup.object({
name: Yup.string().min(5, 'Must be 5 characters or more').required('Required'),
});
function App() {
return (
<Formik
initialValues={{ name: '' }}
validationSchema={validationSchema}
onSubmit={(values) => {
alert(JSON.stringify(values, null, 2));
}}
>
{({ handleSubmit }) => (
<Form onSubmit={handleSubmit}>
<Field
component={TextField}
name="name"
type="text"
label="Name"
fullWidth
margin="normal"
variant="outlined"
/>
<ErrorMessage name="name" component="div" />
<Button type="submit" variant="contained" color="primary">
Submit
</Button>
</Form>
)}
</Formik>
);
}
Best Practices
Accessibility
Ensure your app is accessible to all users.
Keyboard Navigation
Provide keyboard navigation for all buttons and links.
<Button onClick={handleClick} tabIndex={0}>
Click Me
</Button>
Screen Reader Support
Use ARIA attributes to improve screen reader support.
<Button aria-label="delete" onClick={handleClick}>
Delete
</Button>
Accessibility Tips
Always test your app with screen readers and keyboard navigation tools to ensure accessibility.
Performance Optimization
Enhance the performance of your app.
Server-Side Rendering
Use server-side rendering for better performance.
// Setup for server-side rendering involves configuring your server to render React apps on the server-side.
// This is more complex and requires setting up a Node.js server with Next.js or another framework.
Lazy Loading
Lazy load components to improve load times.
const About = React.lazy(() => import('./About'));
function App() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<About />
</Suspense>
</div>
);
}
Code Splitting
Split your code into smaller chunks.
const AnotherComponent = React.lazy(() => import('./AnotherComponent'));
function App() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<AnotherComponent />
</Suspense>
</div>
);
}
Troubleshooting
Common Issues
Problem 1 - Components not rendering correctly
Ensure you have the correct imports and that your components are correctly set up.
Solution
Check your imports and component setup.
// Ensure you have the correct imports
import Button from '@mui/material/Button';
function App() {
return (
<div>
<Button variant="contained">Contained Button</Button>
</div>
);
}
Problem 2 - Theme not applied
Ensure your theme is correctly wrapped around your app.
Solution
Wrap your app with ThemeProvider
.
import React from 'react';
import ReactDOM from 'react-dom';
import { ThemeProvider } from '@mui/material/styles';
import theme from './theme';
import App from './App';
ReactDOM.render(
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>,
document.getElementById('root')
);
Conclusion
Summary of Key Points
- Material UI provides a set of React components following Material Design principles.
- Customization is extensive, allowing you to match your brand's design.
- Use dialogs, snackbars, and menus for interactive elements.
- Enhance accessibility and performance for a better user experience.
Further Resources
Material UI Documentation
Explore the official Material UI documentation for more information and examples.
Community Forums
Join the Material UI community to connect with other developers.
Additional Tutorials
Check out additional tutorials and guides: