In this article, I want to share how to integrate
Material UI in
Next.js applications. We will build a very basic website using Material UI and Next.js.
Prerequisites
I will assume that you have some familiarity with React, but you should be able to follow along even if you are coming from a different programming language. You will also need to have
Node >= 8.10 and npm >= 5.6 on your machine.
Setup
Create a new directory called my-app
:
mkdir my-app
Install next
, react
, and react-dom
in your project directory:
cd my-app
yarn add -E next react react-dom
Install @types/node
, @types/react
, and typescript
if you are going to use TypeScript in your project:
yarn add -DE @types/node @types/react typescript
Open package.json
and add the following scripts
:
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
}
Install Material UI
Install @material-ui/core
in your project directory:
yarn add -E @material-ui/core
Create a theme configuration file utils/theme.ts
:
mkdir utils
touch utils/theme.ts
And, put the following code in the theme configuration file:
import indigo from '@material-ui/core/colors/indigo';
import pink from '@material-ui/core/colors/pink';
import { createMuiTheme } from '@material-ui/core/styles';
const theme = createMuiTheme({
palette: {
primary: indigo,
secondary: pink,
},
});
export default theme;
Create a custom document page pages/_document.tsx
:
import React from 'react';
// Modules
import Document, { Html, Head, Main, NextScript } from 'next/document';
// MUI Core
import { ServerStyleSheets } from '@material-ui/core/styles';
// Utils
import theme from '../utils/theme';
class MyDocument extends Document {
render() {
return (
<Html lang="en">
<Head>
<meta name="theme-color" content={theme.palette.primary.main} />
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;600;700&display=swap" />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
// `getInitialProps` belongs to `_document` (instead of `_app`),
// it's compatible with server-side generation (SSG).
MyDocument.getInitialProps = async (ctx) => {
// Resolution order
//
// On the server:
// 1. app.getInitialProps
// 2. page.getInitialProps
// 3. document.getInitialProps
// 4. app.render
// 5. page.render
// 6. document.render
//
// On the server with error:
// 1. document.getInitialProps
// 2. app.render
// 3. page.render
// 4. document.render
//
// On the client
// 1. app.getInitialProps
// 2. page.getInitialProps
// 3. app.render
// 4. page.render
// Render app and page and get the context of the page with collected side effects.
const sheets = new ServerStyleSheets();
const originalRenderPage = ctx.renderPage;
ctx.renderPage = () => originalRenderPage({
enhanceApp: (App) => (props) => sheets.collect(<App {...props} />),
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
// Styles fragment is rendered after the app and page rendering finish.
styles: [
...React.Children.toArray(initialProps.styles),
sheets.getStyleElement(),
],
};
};
export default MyDocument;
Create a custom app page pages/_app.tsx
:
import React from 'react';
// Modules
import { AppProps } from 'next/app';
import Head from 'next/head';
// MUI Core
import CssBaseline from '@material-ui/core/CssBaseline';
import { ThemeProvider } from '@material-ui/core/styles';
// Utils
import theme from '../utils/theme';
const MyApp: React.FC<AppProps> = ({ Component, pageProps }) => {
React.useEffect(() => {
// Remove the server-side injected CSS.
const jssStyles = document.querySelector('#jss-server-side');
if (jssStyles && jssStyles.parentElement) {
jssStyles.parentElement.removeChild(jssStyles);
}
}, []);
return (
<>
<Head>
<title>My App</title>
<meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" />
</Head>
<ThemeProvider theme={theme}>
<CssBaseline />
<Component {...pageProps} />
</ThemeProvider>
</>
);
};
export default MyApp;
Create the home page page/index.tsx
:
import React from 'react';
// Modules
import { NextPage } from 'next/types';
const HomePage: NextPage = () => {
return (
<Button color="primary" variant="contained">My App</Button>
);
};
export default HomePage;
Start the Development Server
To start the development server, run this command in your terminal:
yarn dev
You can access your development server at http://localhost:3000
, and you will see a Material UI button!
To understand more about Material UI and Next.js, you can visit their official websites:
- How to make strongly-typed React components
TypeScript helps developers to improve their productivity and prevent them from producing bugs.
Published on Mar 10, 2021 · 2 min read
- Basic overview on JavaScript Promise
A promise represents a value that is unknown now that may become known in the future, in other words an asynchronous value.
Published on Mar 10, 2021 · 2 min read
- React Native over-the-air app update with CodePush
CodePush is a tool developed by Microsoft which allows developers to quickly and easily manage and update React Native JavaScript bundles over the air.
Published on Nov 1, 2020 · 7 min read
- Building a simple login form in React Native using React Hook Form
A short step-by-step tutorial about how to build a simple login form in React Native using React Hook Form.
Published on Oct 6, 2020 · 9 min read
- Building floating logo bubbles on Stripe.com using React Hooks
In this tutorial, we are going to clone animating logo bubbles from Stripe.com using React Hooks.
Published on Aug 11, 2020 · 9 min read
- Building custom React Hooks to fetch data from Firebase Firestore
In this article, I want to share my experience of building custom React Hooks to fetch data from Firebase Firestore.
Published on Aug 5, 2020 · 5 min read
- Building a simple login form with Material UI and React Hook Form
In this article, I will give a short step-by-step tutorial about how to build a simple login form with Material UI and React Hook Form.
Published on Jul 23, 2020 · 7 min read
- Introduction to React Hooks
Hooks solve a wide variety of seemingly unconnected problems in React. Whether you're new to React or use it daily, you might recognise some of these problems.
Published on Jul 20, 2020 · 3 min read
- N+1 problem in GraphQL
The n+1 problem occurs because GraphQL executes a separate function – called resolver – for each field.
Published on Jul 17, 2020 · 2 min read
- GraphQL vs REST
GraphQL has been introduced as a revolutionary alternative to REST APIs. However, it has its pros and cons.
Published on Jul 16, 2020 · 3 min read
- Data fetching in Next.js 9.3+
There are two forms of pre-rendering: Static Generation and Server-side Rendering.
Published on Jul 15, 2020 · 6 min read
- When should we consider using third-party libraries?
The most crucial advantage of using third-party libraries is that it helps you to save time because you do not need to develop the functionality that the library gives.
Published on Jul 13, 2020 · 4 min read