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
- Nextjs
- SWR
- Axios
- 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
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
import { createMuiTheme } from "@material-ui/core/styles";
// Create a theme instance.
const theme = createMuiTheme({
palette:{
type:"dark"
}
});
export default theme;
src/pages/_document.js
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
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);
}
};
Top comments (1)
Is SWR good for SEO? When I view page source it doesn't have any content