Next.js Trash Course - Part 2/3 
Tags: nextjs, react, webdev, javascript
Published: 2021-02-26 21:46:46

Hi, dear devs.

Thanks a ton for all the positive comments in the part 1/3 of our [Trash Course](https://dev.to/vinicius77/next-js-trash-course-part-1-3-2dlb). 😊 

It motivates me to keep writing and researching even more in order to delivery high-quality content (or something close to it 😂) for you guys.
 
<hr/>
 ⭐⭐⭐⭐⭐ You all deserve the stars! ⭐⭐⭐⭐⭐
<hr/>

I know it is Friday 📅 so I promise don't waste your time here, ok? 😛

### What will be covered in this part 2/3? 

- Layouts,
- Adding styles (global stylesheets and CSS modules),
- Creating a customized Not Found page,
- Redirecting.

### Part 5 - Layouts 🖼️

Let's imagine a scenario where there is a big application and we want to use both the `Footer` and `Navbar` components we created previously on it. It is possible to just drop them in every page component we need but besides than just repeating code, that is not something good ([DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)), we will also make harder to track these components.
 
In order to avoid these kind of issues we can create layouts, wrap all the different pages with it and reuse the `Layout` component through our application.

1- First step is to create the `Layout` component in the components folder (`/components/Layout.js`) and import the components that we will use to wrap all the `children`.

```jsx
import { Navbar } from './Navbar';
import { Footer } from './Footer';

const Layout = ({ children }) => {
  return (
   {/** We will style it later on :) */}
    <div className="layout-content">      
      <Navbar />
      {children}
      <Footer />
    </div>
  );
};

export default Layout;
```

2- Second step is to wrap the page component(s) with the Layout we want to apply. In your case, the root component of the application `/pages/_app.js`.

```jsx
import '../styles/globals.css'; // SPOILER OF STYLING 👉👈
import Layout from '../components/Layout'; // We import the Layout

function MyApp({ Component, pageProps }) {
  return (
    <Layout>
      {/** We wrap the root component with the layout.*/}
      {/** and pass it as a children of the Layout component*/}
      <Component {...pageProps} />
    </Layout>
  );
}

export default MyApp;
```

3- Third and the last step is to remove the already imported Footer and Layout Components in our home component `pages/index.js`. (Otherwise they will be appearing twice. 👯‍♀️)

```jsx
import Link from 'next/link';

export default function Home() {
  return (
    <div>
      <h1>Hello Next.js</h1>
      <Link href="/about">About</Link>
    </div>
  );
}
```

And that is it! Now the Layout (contaning `Footer` and `Navbar`) is rendering in every single page through our application. I know it is just `React` stuff but "_knowledge does not occupy space_". ⚛️ 😃

### Part 6 - Adding Styles 💅

The application is running fine but let's be honest here: It is horrible! 👹

As any web application, in `Next.js` we can also add styles to it. There are _n_ ways to do so as using `global stylesheets`, `styled JSX`, `inline-style`, `CSS modules` etc. We will learn about two of these methods now.

#### ⚆ Global Stylesheets (`styles/globals.css`)
  This file holds the styles we can apply anywhere in your application. It seems logic I know, but I will point out the differences when between it and `CSS modules`.  

**Important Note**: We are here to learn about `Next.js` and not how to master CSS styling so please don't judge. 😂

```css
@import url('https://fonts.googleapis.com/css2?family=Quicksand:wght@300;400&display=swap');

:root {
  --psy-blue: rgb(188, 152, 255);
  --psy-teal: rgb(3, 129, 129);
}

* {
  box-sizing: border-box;
}

html {
  padding: 0;
  margin: 0;
}

body {
  font-family: 'Quicksand', sans-serif;
  background-color: var(--psy-blue);
  color: var(--psy-teal);
}

.container {
  min-height: 65vh;
}

a {
  color: var(--psy-teal);
  text-decoration: none;
}

.layout-content {
  max-width: 900px;
  margin: 0 auto;
}

nav {
  margin: 10px auto 80px;
  padding: 10px 1px;
  display: flex;
  justify-content: flex-end;
  align-items: flex-end;
  border-bottom: 1px solid var(--psy-teal);
}

nav a {
  margin-left: 10px;
}

nav .brand {
  margin-right: auto;
}

footer {
  display: block;
  text-align: center;
  padding: 30px 0;
  margin-top: 60px;
  color: var(--psy-teal);
  border-top: 1px solid rgb(3, 78, 78);
}
```
If you are wondering: "Where the heck I have imported this file into the application?". It was not you, it was already there in the `pages/_app.js` file. This line, this single line of code ... 👇

```jsx
import '../styles/globals.css';
```

#### ⚇ CSS modules

Allows us to write **individual** styles for each  component. After created the stylesheets file we import it in whatever component needs it. `Next.js` adds some random characters to the end of the classes / selectors names.

**Example:** in your browser (`mouse left-click > "Inspect Element"`) you should see something like:
```css
 <div className="Home_container__2DbTr">...</div>
```

The ending `__2DbTr` indicates the styles will apply only for this component so it avoids `CSS conflicts`. You can think it as an `unique id`.

We could have seem an example on the `Home` component (`/pages/index.js`) which had its own styles imported from the `styles/Home.module.css` file, before we had cleaned up it. 😅

```jsx
import styles from '../styles/Home.module.css';
```

#### Quick rules when add styling: ✏️🗒️

- `CSS Modules` must follow this class name convention: `ComponentName`.`modules`.`css`. (e.g Home.modules.css)
- How to use style:
  If you have, for example, in your `module.css` file something like:
```css
.title a {
  color: #0070f3;
  text-decoration: none;
}
```
You apply this style by:
```jsx
import styles from '../styles/Home.module.css'; // 👈 Importing like mentioned previously
import Link from 'next/link';

export default function Home() {
  return (
    <div className="container">
      <h1>Hello Next.js</h1>
      <div className={styles.title}>
        {/** 👆 applying the styles as shown*/}
        {/** Remember the Link component creates an anchor tag in the DOM* 👇/}
        <Link href="/about">About</Link>
      </div>
    </div>
  );
}
```
Remember again that `<Link>` in the DOM is just an `<a>` tag. 

🧧 **Very Important Note**: The `selectors` must be **pure selectors**, in other words, you must use `class selectors` instead `element selectors` so using the following inside of your CSS module won't work so be aware of that.

```css
a {
  color: #0070f3;
  text-decoration: none;
}
```

### Part 7 - Custom 404 Page ❌😵‍💫

If you try to access a route that doesn't exist (e.g. `http://localhost:3000/you-are-amazing`), `Next.js` has a `default 404 page`. Very often we want to customize our own. 
Luckily, doing that is simpler than you may think.
Inside of the pages folder, we only need to create a `404.js` file and stylize that component using the techniques we have just learned.

```jsx
import Link from 'next/link';

const NotFoundPage = () => {
  return (
    <div className="not-found-page">
      <h1>Page Not Found</h1>
      <p>Looks like this page went on vacation.</p>
      <Link href="/">Home</Link>
    </div>
  );
};

export default NotFoundPage;
```
Now this customized `Not Found` page replaces the `Next.js` default one. I have also added some styling just because. 🙈

```css
.not-found-page {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  color: rgb(221, 80, 15);
}

.not-found-page h1 {
  font-size: 40px;
  letter-spacing: 1.2rem;
}

.not-found-page p {
  font-size: 26px;
}

.not-found-page a {
  color: rgb(221, 80, 15);
  box-sizing: border-box;
  border: 1px solid rgb(221, 80, 15);
  padding: 2px 20px;
  background-color: rgb(183, 182, 255);
}

.not-found-page a:hover {
  text-decoration: underline;
}
```

### Part 8 - Redirecting ♺

Sometimes for some reason we need to automatically redirect an user to a determined page in the web site.
 
We can think in a situation where a lost user hit our `Not Found Page` and we would like to redirect his/her to our `Home` page, for example. Let's implement _redirecting_ using both the `React's useEffect`, `Next's useRouter` hooks and the `SetTimeout()` javascript function. (You need to admit, it has been a long time since you last used it, right? 🕰️)

So the new version of our 404 page will look like this:

```jsx
import { useEffect } from 'react';
import { useRouter } from 'next/router'; // we import the router
import Link from 'next/link';

const NotFoundPage = () => {
  const router = useRouter(); // initialize it

  useEffect(() => {
    setTimeout(() => {
      router.push('/'); // and define where to redirect
    }, 3000);
  }, []);

  return (
    <div className="not-found-page">
      <h1>Page Not Found</h1>
      <p>Looks like this page went on vacation.</p>
      <Link href="/">Home</Link>
    </div>
  );
};

export default NotFoundPage;
```
In short, `the useEffect hook` will run only in the first rendering (`[]`) of the component, trigger the `setTimeout` to redirect to the `Home` page (`router.push('/')`) after 3 seconds (`3000`).

Alright! That's it for the part 2/3. As I have promised in the beginning I wouldn't disturb to much so I tried to make it smooth.

### What will be covered in this [part 3/3](https://dev.to/vinicius77/next-js-trash-course-part-3-3-3igc)? 🤔
- Static Assets, Custom Page Title and Metadata
- Fetching Data
- Dynamic Routes

Looks like there is just few topics remaining to be covered but believe me, they will consume a lot of your time. My aim here is that at the end of this series you will be able to build your own `Next.js` applications.

For now, thanks a lot for following along until here. 🙏

If you could learn something new from these posts I am going to be really glad. Also if you have any doubt about what was covered until now, feel free to message me and I am going to try to explain the topic in a more understandable way. 😃

By the way, I answer all the comments. Not as fast as I wish but if you comment in any of my posts I guarantee you will be answered, soon or later. 🦄

You are free to go now! See you in the last part.

Have an amazing weekend and be safe! ❤️‍