How to Implement Material UI With Next.js

1841 VIEWS

·

Next.js is a React based JavaScript framework for building frontend applications. The Material UI library, on the other hand, offers ready-made components you can utilize to create your frontend applications. It offers several UI components, like InputText, Typography, Menu, Button, Dialogs, Icons, App bar TextField, etc. This collection of ready-to-use Material UI components aids in accelerating the implementation of application development. The components can be used in your frontend application by simply importing them. This makes it perfect to implement Material UI with any Next.js app.

In this guide, we will learn how to add Material UI to a Next.js app, as well as how to create and implement Material UI components with Next.js.

To comfortably implement Material UI (MUI) with Next.js, this article will show how to create a Next.js todo app that uses Material elements. At the end of this todo example, you will learn how to use the following components using Material UI:

  • Web app AppBar.
  • Layout Box, Grid, and Container.
  • Web app Toolbar.
  • Button and IconButton.
  • Typography component for variant mappings props with the Material semantic elements.
  • Menu, MenuIcon and MenuItem.
Prerequisites

To continue in this article, it is essential to have the following:

  • Node.js installed on your computer.
  • Basic knowledge of working with Next.js.

Setting Up the Application

On your preferred working directory, run the following command to create a basic Next.js app:

npx create-next-app material-ui-next --use-npm

Once the installation is done, navigate to the newly created directory:

cd material-ui-next

You will use this basic application to implement Material UI With Next.js. Go ahead and install the dependencies for the Material UI that will be used in this article:

npm install @mui/material @mui/icons-material @emotion/styled @emotion/react

Check this guide and learn more dependencies that you can implement in your Material React UI tools.

To test if the created application works as expected, start the development server using the following command:

npm run dev

Finally, proceed to http://localhost:3000; you will be able to view the default page of the application.

Setting Up Todos

To create this todo app, you will require some data source that you can use to render your components. Head over to your project directory and create a data directory. Inside the data directory, create a todos.json file. Then enter a bunch of dummy todos as follows:

[
    {
        "title": "Going to the market",
        "description": "Going to the market",
        "completed": false
    },
    {
        "title": "Cooking lunch meal",
        "description": "Cooking lunch meal",
        "completed": false
    },
    {
        "title": "Working on a website.",
        "description": "Working on a website",
        "completed": false
    },
    {
        "title": "Watching an episode",
        "description": "Watching an episode",
        "completed": false
    }
]

Feel free to add as many todos as possible using the above data as an example.

Setting Up the Components Using Material UI with Next.js

Material UI has components. Let’s dive and check how to implement Material UI components using Next.js.

On the project root directory, create a components directory. Inside this folder, create two files:

  • Navbar.js: For the navigation bar.
  • Card.js: For showing each individual todo.
Create a Navbar Using Material UI With Next.js

In Navbar.js, create your Navbar as follows:

  • Import Material UI components that you want to use.
    import * as React from 'react';
    import AppBar from '@mui/material/AppBar';
    import Box from '@mui/material/Box';
    import Toolbar from '@mui/material/Toolbar';
    import IconButton from '@mui/material/IconButton';
    import Typography from '@mui/material/Typography';
    import Menu from '@mui/material/Menu';
    import MenuIcon from '@mui/icons-material/Menu';
    import Container from '@mui/material/Container';
    import Button from '@mui/material/Button';
    import MenuItem from '@mui/material/MenuItem';
    import AdbIcon from '@mui/icons-material/Adb';
  • Create a Page link that directs to the home page.
    const pages = ['Todos'];
  • Set up the states and the Navbar menus.
    const Navbar = () => {
        const [anchorElNav, setAnchorElNav] = React.useState(null);
    
        const handleOpenNavMenu = (event) => {
            setAnchorElNav(event.currentTarget);
        };
    
        const handleCloseNavMenu = () => {
            setAnchorElNav(null);
        };
    };
    
    export default Navbar;
  • Create a render function. This will include all the Material elements you want to display in your Navbar. This goes inside the Navbar() created above. Add the following return() function right above the export default Navbar; method.
    return (
    <AppBar position="static">
        <Container maxWidth="xl">
            <Toolbar disableGutters>
                <AdbIcon sx={{ display: { xs: 'none' , md: 'flex' }, mr: 1 }} />
                <Typography variant="h6" noWrap component="a" href="/" sx={{ mr: 2, display: { xs: 'none' , md: 'flex' },
                    fontFamily: 'monospace' , fontWeight: 700, letterSpacing: '.3rem' , color: 'inherit' ,
                    textDecoration: 'none' , }}>
                    My todos
                </Typography>
    
                <Box sx={{ flexGrow: 1, display: { xs: 'flex' , md: 'none' } }}>
                    <IconButton size="large" aria-label="account of current user" aria-controls="menu-appbar"
                        aria-haspopup="true" onClick={handleOpenNavMenu} color="inherit">
                        <MenuIcon />
                    </IconButton>
                    <Menu id="menu-appbar" anchorEl={anchorElNav} anchorOrigin={{ vertical: 'bottom' , horizontal: 'left' ,
                        }} keepMounted transformOrigin={{ vertical: 'top' , horizontal: 'left' , }}
                        open={Boolean(anchorElNav)} onClose={handleCloseNavMenu} sx={{ display: { xs: 'block' , md: 'none'
                        }, }}>
                        {pages.map((page) => (
                        <MenuItem key={page} onClick={handleCloseNavMenu}>
                        <Typography textAlign="center">{page}
    
                        </Typography>
                        </MenuItem>
                        ))}
                    </Menu>
                </Box>
                <AdbIcon sx={{ display: { xs: 'flex' , md: 'none' }, mr: 1 }} />
                <Typography variant="h5" noWrap component="a" href="" sx={{ mr: 2, display: { xs: 'flex' , md: 'none' },
                    flexGrow: 1, fontFamily: 'monospace' , fontWeight: 700, letterSpacing: '.3rem' , color: 'inherit' ,
                    textDecoration: 'none' , }}>
                    My todos
                </Typography>
                <Box sx={{ flexGrow: 1, display: { xs: 'none' , md: 'flex' } }}>
                    {pages.map((page) => (
                    <Button key={page} onClick={handleCloseNavMenu} sx={{ my: 2, color: 'white' , display: 'block' }}>
                        {page}
                    </Button>
                    ))}
                </Box>
    
            </Toolbar>
        </Container>
    </AppBar>
    );

The above Navbar will display the following:

  • A Container wrapped inside an AppBar to display different Toolbar elements.
  • An AdbIcon.
  • A Typography that displays My todos inside the Toolbar.
  • A Box layout that displays the IconButton and Menu of MenuItem that display the Todos Typography as a page.
Create a Card Component Using Material UI With Next.js
  • In Card.js create the following Material UI components:
    import * as React from 'react';
    import Card from '@mui/material/Card';
    import CardContent from '@mui/material/CardContent';
    import Typography from '@mui/material/Typography';
    import { CardActionArea } from '@mui/material';
    
    export default function TodosCard({ todo }) {
        return (
            <Card>
                <CardActionArea>
                    <CardContent>
                        <Typography gutterBottom variant="h5" component="div">
                            {todo['title']}
                        </Typography>
                        <Typography variant="body2" color="text.secondary">
                            {todo['description']}
                        </Typography>
                    </CardContent>
                </CardActionArea>
            </Card>
        );
    }

This component will have the following Material UI elements:

  • A CardContent is defined inside a Card to display a CardActionArea for todos.
  • A Typography to display the todo title content.
  • A Typography to display the todo description content.

Displaying Todos Using Material UI

Now that you have the Material components ready let’s display them using Next.js. In pages/index.js:

  • Import the necessary packages and import the components you have created above:
    import Head from 'next/head'
    import fs from 'fs';
    import { join } from 'path';
    import Navbar from '../components/Navbar';
    import Card from '../components/Card';
    import { Container, Grid } from '@mui/material';
  • Get the todos from the file path:
    export async function getServerSideProps() {
      // get all the todos.
      let todos_path = join(__dirname, '..', '..', '..', 'data', 'todos.json');
      let todos = await fs.promises.readFile(todos_path, 'utf8');
      return {
        props: {
          "todos": JSON.parse(todos)
        }
      }
    }
  • Render the components:
    export default function Home({ todos }) {
      return (
        <div>
          <Head>
            <title>Todos App</title>
            <meta name="description" content="Todos app with Material UI" />
            <link rel="icon" href="/favicon.ico" />
          </Head>
    
          <Navbar />
    
          <Container>
            {
              todos.length > 0 ? (
                todos.map((todo, index) => (
                  <Grid key={index} marginBottom={4} marginTop={4}>
                    <Card todo={todo} key={index} />
                  </Grid>
                ))
              ) : (
                <p>
                  No saved todos yet!!
                </p>
              )
            }
          </Container>
        </div>
      )
    }

Once you get the todos lists, render the todos using Grid, where each Card represents one todo item.

To ensure that the development is running, go to http://localhost:3000 on your browser to check how your components render:

Conclusion

Congratulations! You now have the basics of how to add Material components to Next.js. I hope you found this guide helpful. Happy coding!


Joseph is fluent in Fullstack web development and has a lot of passion for DevOps engineering. He loves to write code and document them in blogs to share ideas.


Discussion

Click on a tab to select how you'd like to leave your comment

Leave a Comment

Your email address will not be published.

Menu
Skip to toolbar