Complete setup of Nextjs, SWR , Axios and Material UI with SSR for your upcomming projects
Tags: nextjs, axios, swr, materialui
Published: 2021-05-23 03:27:20

Hello Community,

In this trending world Reactjs is a perfect library for making user interfaces.
But we knew if we want better SEO,SSR, better Image optimisation, Code splitting etc we have better  one Nextjs which is build on top of Reactjs for production.

Material ui is a reactjs based material component library mainly focused on providing awesome and mind blowing design system for web apps.

When we work on frontend project we have to care about caching because we make api request to another server for the purpose of getting data.SWR is a strategy to first return the data from cache then send the fetch request and finally come with the up-to-date data.

Axios is used for making api call to our server. You can use Axios for your both client side and server side (getServerSideProps and getStaticProps) hence it is easy and relevant for api request

## Library and Framework we will using
1. Nextjs
2. SWR
3. Axios
4. Material UI


## Lets jump to setup

#### Initialize a new brand nextjs project

```
npx create-next-app

```

#### Installing dependencies 

```
yarn add axios swr @material-ui/core @material-ui/icons

```

`src/pages/_app.js`

```javascript

import React from "react"
import { ThemeProvider } from "@material-ui/core/styles";
import CssBaseline from "@material-ui/core/CssBaseline";
import theme from "../theme";
import Navbar from "../components/Header/Navbar";
import Footer from "../components/Footer/Footer";

import Axios from "axios";
import { SWRConfig } from "swr";

import { colors, Container, makeStyles } from "@material-ui/core";

Axios.defaults.baseURL = process.env.NEXT_PUBLIC_SERVER_BASE_URL + "/api";
Axios.defaults.withCredentials = true;

const fetcher = async (url) => {
  try {
    const res = await Axios.get(url);
    return res.data;
  } catch (err) {
    throw err.response.data;
  }
};

const useStyles = makeStyles((theme) => ({
  main: {
    flex: 1,
    padding: "16px 0px",
  },
}));

export default function App() {
  const classes = useStyles();
  const { Component, pageProps } = props;

  React.useEffect(() => {
    // Remove the server-side injected CSS.
    const jssStyles = document.querySelector("#jss-server-side");
    if (jssStyles) {
      jssStyles.parentElement.removeChild(jssStyles);
    }
  }, []);

  return (
    <React.Fragment>
      <SWRConfig
        value={{
          fetcher,
          dedupingInterval: 10000,
        }}
      >
        
            <ThemeProvider theme={theme}>
              <CssBaseline />
              <div
                style={{
                  display: "flex",
                  flexDirection: "column",
                  justifyContent: "space-between",
                  minHeight: "100vh",
                  backgroundColor: colors.grey[200],
                }}
              >
                <nav>
                  <Navbar />
                </nav>

                <main className={classes.main}>
                  <Container>
                    <Component {...pageProps} />
                   
                  </Container>
                </main>

                <footer>
                  <Footer />
                </footer>

              
              </div>
            </ThemeProvider>
         
      </SWRConfig>
    </React.Fragment>
  );
}

```

`src/theme.js`
```javascript


import { createMuiTheme } from "@material-ui/core/styles";

// Create a theme instance.
const theme = createMuiTheme({
    palette:{
        type:"dark"
    }
});

export default theme;

```


`src/pages/_document.js`


```javascript

import React from "react";
import Document, { Html, Head, Main, NextScript } from "next/document";
import { ServerStyleSheets } from "@material-ui/core/styles";
import theme from "../theme";

export default class MyDocument extends Document {
  render() {
    return (
      <Html lang="en">
        <Head>
          {/* PWA primary color */}
          <meta name="theme-color" content={theme.palette.primary.main} />
          <link
            rel="stylesheet"
            href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,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(),
    ],
  };
};


```


#### Lets do some best practices with ssr and swr together

```javascript

import Head from "next/head";
import axios from "axios";
import useSWR from "swr";
import Categorycard from "../components/Category/Categorycard"
import CategoryLoading from "../components/Category/CategoryLoading"

export default function Home({ categories }) {
const {data,error} = useSWR("/categories",{initialData:categories})
  return (
    <div>
      <Head>
        <title>Categories</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <div>
        {/*loop through category list using `data`    */}
        {!data ? <CategoryLoading /> : data.categories.map(category=>(
<div key={category._id}>
<CategoryCard category={category}  />
</div>
))}
      </div>
    </div>
  );
}
export const getServerSideProps = async () => {
  try {
    const res = await axios.get("/categories");

    return {
      props: {
        categories: res.data,
      },
    };
  } catch (error) {
    console.log(error);
  }
};


```


#### Good luck for your next project..