Getting Started with React Material-UI

So I wanted to learn Material UI since it seems to be the best way to use Material Design in a React Applications.

But the problem is that the official docs assume that you already are familiar with other UI frameworks for react and just point you to example projects instead of covering the basics on how to start a project using the toolkit.

So I decided to create my own documentation just for that and here it is.

In this blog entry I’m going to create a very simple React App that does nothing, but that it looks good thanks to Material-UI.

TOC

What is Material-UI ?

If you are here is very probable that you already know Material-UI is… But just in case, Material-UI its just a number of React components styled using the material design principles, that are ready to use in any React App.

If you want to start a React Project and don’t want to get caught up in the details of styling you app, then Material-UI is just what you need.

Create a react project and install Material-UI

Lets start our App by doing the following:

Note I’m using yarn instead of npm for installing packages and executing commands since its faster. You can use npm without any problems.

Create the react app and install Material-UI

You must know this by now. If not, then you should be following this tutorial instead

mkdir react-material-ui-tutorial
cd react-material-ui-tutorial
yarn create react-app . # npx create-react-app .
yarn add @material-ui/core

Add the Roboto Font and add the responsive meta-tag

This 2 lines should go into public/index.html before the closing of the <head> tag.

The first one makes our layout to be responsive. The second one loads the Roboto font form Google Fonts

<meta
  name="viewport"
  content="minimum-scale=1, initial-scale=1, width=device-width"
/>
<link
  href="https://fonts.googleapis.com/css?family=Roboto:300,400,500&display=swap"
  rel="stylesheet"
/>

index.html changes

We could bundle the font using the package typeface-roboto but we would increase the size of our bundle considerable. If you want to know more follow this link

Project cleanup

Now lets remove unneeded files the src/ folder, leaving only index.js and App.js in that dir.

rm src/{App.css,App.test.js,index.css,logo.svg,serviceWorker.js,setupTests.js}

Were using some Bash magic there. Curly brackets allow you to append a list of files.

The src/ directory should look like this:

$ tree src
src
├── App.js
└── index.js

0 directories, 2 files

Refactor App.js and index.js

Then refactor src/index.js so it doesn’t try to import the removed files. At the end it should look like this:

// src/index.js
import React from "react"
import ReactDOM from "react-dom"
import App from "./App"

ReactDOM.render(<App />, document.getElementById("root"))

And finally. We should refactor App.js so it does not issue any errors:

// src/App.js
import React from "react"

function App() {
  return (
    <div className="App">
      <h1>React Material-UI Tutorial</h1>
    </div>
  )
}

export default App

Now, lets start the development by issuing this in the terminal:

yarn start

Image of the title Exercises

Great now we can start adding Material-UI components

Normalize or CssBaseline

If you’ve worked with a framework like Bootstrap, Bulma, Tailwind, etc. You’ve noticed that one of the first things they recommend is to use a CSS library like normalize.css or reboot.css to unify or reset the display of native controls.

Material-UI has its own Control just for that and it called CssBaseline.

Adding baseline couldn’t be easier. Just import the component and add it in src/index.js

// src/index.js
import React from "react"
import ReactDOM from "react-dom"
import CssBaseline from "@material-ui/core/CssBaseline"
import App from "./App"

ReactDOM.render(
  <>
    <CssBaseline />
    <App />
  </>,
  document.getElementById("root")
)

What did we do?

That would render the following:

Image of the styles changed

Notice how the font is a sans-serif family font, and the background is now a light gray. Also, this is how its going to look the same in all browsers. So we have a common Baseline.

Adding our first elements

Adding Material-UI components is usually a 2 step process:

Of course you can (and sometimes must) use properties to configure the component to your needs.

So lets change our src/App.js file to include some content and to add our first components. We’ll be adding a couple of buttons:

// src/App.js
import React from "react"
import { Button } from "@material-ui/core"

function App() {
  return (
    <div className="App">
      <h1>React Material-UI Tutorial</h1>
      <h2>This Could be a subtitle</h2>
      <p>And this is a paragraph</p>
      <Button variant="contained" color="primary">
        A Primary button
      </Button>
      <Button variant="contained" color="secondary">
        A Secondary button
      </Button>
    </div>
  )
}

export default App

Which would render this:

Some test content

As you can see, we now have a page with 2 buttons: One primary (the blue one) and one secondary.

Typography

One important aspect of the Material Design Language is the font management.

If you go over the Material Design Documentation, you can see that there are a ton of options and rules for font usage and management.

That’s why Material-UI has the very powerful component <Typography /> which as a ton of options as you can see in the documentation. The cool thing is that is only one component.

So lets change hour headings and paragraphs to use the <Typography /> component:

import React from "react"
import { Button, Typography } from "@material-ui/core"

function App() {
  return (
    <div className="App">
      <Typography variant="h1" align="center">
        React Material-UI Tutorial
      </Typography>
      <Typography variant="h2">This Could be a subtitle</Typography>
      <Typography color="textSecondary">And this is a paragraph</Typography>
      <Button variant="contained" color="primary">
        A Primary button
      </Button>
      <Button variant="contained" color="secondary">
        A Secondary button
      </Button>
    </div>
  )
}

export default App

That will yield

Using Typography instead of headings and paragraphs

Now we’re starting to make some progress.

Create layouts using Grid

Right now our content seems kind of Thrown out There. that’s because we’re not using any kind of layout or placement.

Lets fix that by using a Material-UI Grid system so our content is in the middle and centered. Lets edit src/App.js with the following:

import React from "react"
import { Button, Typography, Grid, Container } from "@material-ui/core"

function App() {
  return (
    <div className="App">
      <Container maxWidth="md">
        <Grid item md={12}>
          <Typography variant="h1" align="center">
            React Material-UI Tutorial
          </Typography>
          <Typography variant="h2">This Could be a subtitle</Typography>
          <Typography color="textSecondary">And this is a paragraph</Typography>
          <Grid container>
            <Grid item md={6}>
              <Button variant="contained" color="primary">
                A Primary button
              </Button>
            </Grid>
            <Grid item md={6}>
              <Button variant="contained" color="secondary">
                A Secondary button
              </Button>
            </Grid>
          </Grid>
        </Grid>
      </Container>
    </div>
  )
}

export default App

Using the Material-UI Grid System

If you look closely, you can see that we added a <Container /> tag and multiple <Grid /> tags.

If you’ve worked with Bootstrap you’ll see that <Container /> works very similar to the .container Bootstrap class: It incloses the content in a container with a fixed with. In my case I used a container of 960px wide, hence the maxWidth="md" parameter.

Keeping the analogy to Bootstrap, you can see that the <Grid /> component works both as the .row and the .col Boostrap classes.

When used with the parameter container the Grid component creates a row that contains one or more columns. If you want to be more technical, the <Grid container /> creates an element with display: flex.

When used with the item parameter, it works like the .col-xx-## Boostrap class: It create a column inside the row. And again, being technical, it means create an element with flex-grow and flex-basis.

One last peace of important information. Like most of the CSS frameworks it works by the 12 column paradigm. Dividing the with of the canvas in 12 columns. And it is very important that on the <Grid item /> you also specify either xs, sm, md, lg or xl. Otherwise Material-UI wont know how big or small is the column and it wont stretch to fill the required space.

If you want to know more about the Grid parameters, you can browse the API documentation.

Paper

The idea behind Material Design is to emulate how humans perceive materials with the use of shadows and layers.

So we have Paper which is a way to emulate a sheet of paper with elements over it.

We’re going to use Paper to enclose our app and making it more organized.

// App.js
import React, { useState } from "react"
import { Typography, TextField, Paper } from "@material-ui/core"

function App() {
  const [excercises, setExcercises] = useState([])
  const [title, setTitle] = useState("")

  return (
    <Paper clssName="App">
      <Typography component="h2" variant="h1" align="center" gutterBottom>
        Excercises
      </Typography>
      <form>
        <TextField
          name="title"
          label="excercise"
          margin="normal"
          value={title}
          onChange={e => setTitle(e.target.value)}
        />
      </form>
    </Paper>
  )
}

export default App

Notice that we are including all the Material-UI elements ant that now everthihng is inclosed in <Paper> instead of a <div>

Alter the CSS

Create a Theme

We’re going to start by creating a theme.

But do not get intimidated. We’re just going to change the primary and secondary button colors. This will give us an idea on how themes works in React.

The first step is to create a theme.js file and call createMuiTheme with our new theme parammeters.

// src/theme.js
import { createMuiTheme } from "@material-ui/core/styles"

const theme = createMuiTheme({
  palette: {
    primary: {
      main: "#00695c",
    },
    secondary: {
      main: "#c0ca33",
    },
    background: {
      default: "#fff",
    },
  },
})

export default theme

And change index.js so the app supports themes:

// src/index.js
import React from "react"
import ReactDOM from "react-dom"
import CssBaseline from "@material-ui/core/CssBaseline"
import { ThemeProvider } from "@material-ui/core/styles"
import App from "./App"
import theme from "./theme"

ReactDOM.render(
  <ThemeProvider theme={theme}>
    <CssBaseline />
    <App />
  </ThemeProvider>,
  document.getElementById("root")
)

And we would have the following:

Theme color changes

Other Tutorials

Additional Material-UI documentation is kind of scarce and there aren’t many good tutorials that cover the basic. So here are a couple that you might want to check out: