Introduction to the basics of Next.js
Tags: nextjs, node, react, tutorial
Published: 2018-08-22 17:14:51

---
title: Introduction to the basics of Next.js
published: true
description: First part to the basics of next.js
tags: [nextjs, node, react, tutorial]
cover_image: https://thepracticaldev.s3.amazonaws.com/i/904pyn939cfjx762qry9.png


---



Next.js is a framework that renders react applications on the server. This means when we create a normal react app (using `create-react-app` for example) and load it to the browser, all the content is created by client-side javascript. Hence users or devices that don't have javascript will not be able to access your app.

You can see this in action, open a react application in the browser then view the page source. You will not see the content you've created! In fact, if the project was created through `create-react-app` you'll see this:

```
<noscript>
  You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
```

Which is obvious as all we're doing with react is appending content to `#root`(hence `document.getElementById('root')`). Content that vanishes if javascript is disabled.

Hence Next.js, it fixes that issue for us.

Whilst learning next.js I am trying to create a small application that will have the basic functionality of instagram - a mini instagram clone if you like. I know that the code we'll write today will not be scalable, hence will not contribute that much to the react application but it will cover the basics of next.js

## Let's get started

First we need to initialise `npm` and install the only packages needed for next.js to work:

```
npm init
npm install --save next react react-dom
```

(If you use `yarn` you know what to do)

Now we need to add the following scripts to the generated `package.json`:

```
  "scripts": {
    "start": "next"
  },
```

When we want to run this app in the browser we'll need to run `npm start`.


Next.js allows us to organise our routes via pages. In this tutorial we'll create two pages to see how they can interact. Let's first create the index page. It needs to be at `./pages/index.js`. In there add the following:

```javascript
export default () => (
    <div className="app">
        <header>
            <h1>gallery</h1><h2>Original art</h2>
        </header>
    </div>
)
```

And that's it. 

If we run `npm start` we'll have the index page displayed. And of course, the most important thing here, if you view the page source, you'll now see the above HTML "hard coded" for us by next js.

### Styling 

CSS styles can go right into the `pages/index.js`. Making each section modular. Let's make that header pretty:

```javascript

export default () => (
    <div className="app">
        <header>
          <h1><Link href={{ pathname: '/' }}><a>gallery</a></Link></h1>
        </header>
        <style jsx>{`
            @import url('https://fonts.googleapis.com/css?family=Oleo+Script');
            //... you can get the full code at github
            header h1{
                font-family: 'Oleo Script', cursive;
                font-size: 25rem;
                color: #AD0044;
                text-shadow: #7F0D23 0px 0 40px;
                letter-spacing: -20px;
                
                display: inline-block;
            }
            h2{
                font-size: 3.5rem;
                color: white;
                text-shadow: none;
                letter-spacing: normal;
                font-weight: normal;
                font-family: 'Dancing Script', cursive;
                position: absolute;
                top: 50%;
                left: 50%;
            }
              
        `}</style>
    </div>
)

```

From the documentation "We bundle styled-jsx to provide support for isolated scoped CSS"

Adding styles this way feels like a hack! I like the external styles better, but it really does help with keeping everything isolated. I just need to get used to it - maybe. 

### Adding components

Let's just further split this code up so that it does not get messy by adding a layout component in `./components/Layout.js`

```javascript
import Link from 'next/link'
import Head from 'next/head'

export default ({ children, title = 'gallery: original art' }) => (
    <div>
        <Head>
        <title>{ title }</title>
        <meta charSet='utf-8' />
        <meta name='viewport' content='initial-scale=1.0, width=device-width' />
        </Head>
        <div className="app">
            <header>
                <h1><Link href={{ pathname: '/' }}>gallery</Link></h1>
                <h2>Original art</h2> 
            </header>
            { children }
            <footer>
            Footer
            </footer>
        </div>
        <style global jsx>{`
            :root {
                --green:  #65C5D9; 
                --white: #F4F5F7;
                --light-gray: #EAEEEF;
            }
            ...
            body{...}
        `}</style>
        <style jsx>{`
            header{ ...}
            header h1 a{ ...}
            h2{....}
            footer { ...}
              
        `}</style>
    </div>
)
```

Few important things to note above: 

1. Next.js gives us a `Head` component where by we can manipulate what goes inside the HTML `<head>` tag. For example you might want more meta information.
2. We should use the `Link` component to navigate through the pages. It does require an anchor tag as well. I added an empty anchor tag but Next does populate it accordingly.
3. I used two style tags, one being `global`. The perfect example are the css variables and the body tag. Each page/component needs access to that information, hence `global`.

Back in the `./pages/index.js` we proceed as such:

```
import Layout from '../components/Layout';
export default () => (
    <Layout>
       <p>this is the content </p>
    </Layout>
)
```

## Working with some data.

We could convert the `Index` page component to a react component and get the data in the react component lifecycle or keep going with the stateless function approach. For this tutorial we're going to keep it simple and will not introduce react components (we'll do that in the next tutorial)

```
import Layout from '../components/Layout';
import getPhotos from '../data/data.js'
const Index = (props) => (
    <Layout>
       <p>{props.images[0].tagline}</p>
    </Layout>
)
Index.getInitialProps = async ({ }) => {
  // Would fetch data
  return {  images: getPhotos()  } // return { images: [ { }, { } ] }
}

export default Index
```

`getInitialProps` we would perform fetch operations and pass the fetched data to the `Index` props, but we are hard coding it here just for convenience. We have the hard coded data at `./data/data.js` which looks like this: 

```javascript
export default () => {
    return [
        {
            id: 0,
            tagline: 'You\'re looking at me punk?', 
            image: '927756_283684128492129_838664181_n',
            likes: 2,
            comments: [
                {
                    user: 'rex2018',
                    body: 'Hey this is dope! xxx'
                }
            ]
        },
        ...
    ]
  }
```

All that data is available through the props. How we play with that data inside the `Index` component is basic react stuff. First lets edit the `Index` component 

```javascript
import Layout from '../components/Layout';
import getPhotos from '../data/data.js'
import Photo from '../components/Photo';
const Index = (props) => (
    <Layout>
       {
        props.images.map((image, key) => <Photo id={key} id={key} data={image} />)
       }
    </Layout>
)
...
```

We loop through each image and render a `Photo` component. We need to create that component at `./components/Photo.js`.

```javascript
import CommentsFunctionality from './InteractiveButtons'
import Link from 'next/link'

export default (props) => {
    return (
        <div className="photoComponent">
            <div style={{flex: '1 0 auto'}}>
                <Link href={{ pathname: '/photo', query: { id: props.id } }}>
                    <img src={`/static/art/${props.data.image}.jpg`} alt=""/>
                </Link>
                <div className="meta">
                    <p className="tagline">{props.data.tagline}</p>
                    <CommentsFunctionality likes={props.data.likes} />
                </div>
            </div>
            <style>{`
                .photoComponent {
                    ...
                }
            `}</style>
        </div>
    )
}
```

To recap, in `./pages/Index.js` we loop through all the images. For each image we render the above `Photo` component. The new thing in there is that I decided to move a little bit of code into a separate `InteractiveButtons` component. *Initially I did so purely to keep the CSS of `Photo` component clean*. Anyway, heres the code for `InteractiveButtons`

```javascript
import { MdModeComment, MdFavoriteBorder } from 'react-icons/md'
export default ({likes}) => (
    <div className="meta">
        <a href="/" className="heart"><MdFavoriteBorder />34</a>
        <a href="/"><MdModeComment />{likes}</a>
        <style>{`....`}</style>
    </div>
)
```

I just found the `react-icons` npm module whilst looking for a way to add icons without downloading any css framework, and  I really like this. It's so easy to use.  You can see all the icons provided [here](https://react-icons.netlify.com/#/). Above I am requesting `MdModeComment` and `MdFavoriteBorder` from the Material Design icons (hence `/md`)

### Static Files 

In the `./components/Photo.js` component we are trying to access the image file from a `static` directory. All we need to do is to create that directory and add the image file, and Next.js takes care of the rest.

The end result so far:

![](https://thepracticaldev.s3.amazonaws.com/i/n2dn0aoi6jt0m12g9pht.png)

## Creating another page

We now need to be able to click on one of the above photos and see more information about them. 

In the `./components/Photo.js` component we had this code

```javascript
<Link href={{ pathname: '/photo', query: { id: props.id } }}>
    <img src={`/static/art/${props.data.image}.jpg`} alt=""/>
</Link>
```

Which means, on click we go to `/photo?id=0`. So the `Link` component accepts a query where we can add our own query strings. In this case we simply get the id from the props and pass it on. 

We then need to create `./pages/photo.js` page.


```javascript
import Layout from '../components/Layout';
import Photo from '../components/Photo';
import CommentsFunctionality from '../components/InteractiveButtons'
import getPhotos from '../data/data.js' 
const PhotoPage = (props) => (
    <Layout>
        <div className="container">
            <div className="display_image">
                <img src={`/static/art/${props.image.image}.jpg`} alt=''/>
                <CommentsFunctionality />
            </div>
            <div className="comments">
                <p className="tagline">{props.image.tagline}</p>
                {
                    props.image.comments.map((comment, key) => <p key={key}><strong>{comment.user}:</strong>{comment.body}</p>)
                }
                <form className="comment-form" >
                    <input type="text"placeholder="Author" />
                    <input type="text"  placeholder="comment..." />
                    <input type="submit" hidden />
                </form>
            </div>
        </div>
        <style>{` `}</style>
    </Layout>
)

PhotoPage.getInitialProps = async ({query}) => {
    // could fetch data here
    let {id} = {...query}
    let image = getPhotos().find(m => m.id == id)
    return { image } 
}

export default PhotoPage
```

The important functionality is inside `getInitialProps`. Amongst other information `getInitialProps` has access to the query string, hence we pass the as `{query}`, from which we get the id that comes from the index page. Then we just find the `image` object that has the same id and pass it as the component props.

That's the only reason I added the data in a separate file (at `./data/data.js`). The most basic way of showing how `getInitialProps` could fetch data based on the query strings. The fetch url would look something like this `fetch("http:.../" + id)`

The single photo page is done:

![](https://thepracticaldev.s3.amazonaws.com/i/irlbts6oerwyguyksoo3.png)

## Conclusion

As it can easily be seen this was not the best approach when it comes to handling data. We would really need to add react components and make use of react's component life cycle. Though I would argue even that would fall short compared to redux. 

In the next tutorial, as I said, we'll use react components, fetch the exact same data from an API and get the likes and comments more dynamicly.

Meanwhile you can get all this code in [github (branch 'part1')](https://github.com/aurelkurtula/basics-of-nextJS/tree/part1)

{% link https://dev.to/aurelkurtula/introduction-to-the-basics-of-nextjs---part-two-pad %}