How to Render React on the Server-Side With Next.js

How to Render React on the Server-Side With Next.js

Building a quote app with React + Next.js
Ferenc AlmasiLast updated 2021 November 11 • Read time 10 min read
Next.js is a framework for React that lets you render your pages on the server-side. Learn how you can use it to build apps with its powerful API.
  • twitter
  • facebook
React

Next.js is a framework for React that lets you render your pages on the server-side instead of doing it on the client. It comes with a handful of cool features already built-in, such as code splitting, routing, pre-fetching, support for CSS modules or Typescript, and much more.

In this tutorial, we are going to build a simple application that will fetch and display quotes from famous people that we can later filter by author. This way, we can have a look at how you can set up a new Next.js project, how to add pages and public assets such as images, how to add routing and style your pages, or how to fetch data from an API.

How the Next.js app will look like
The output of the tutorial

How to Set Up Next.js

Fortunately, to set up a Next.js project, you won’t have to do much as the framework doesn’t require any configuration. Create a new folder and run npm init -y to create an empty package.json file with the default values, then install these three dependencies:

npm i next react react-dom

Next, modify your package.json file and add these three new scripts:

Copied to clipboard!
"scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
},
package.json

Now you can run npm run dev to start a development server. The other two scripts are used for production builds:

  • next build: Creates a production build for the application
  • next start: Starts a production server for Next.js

How to Add Pages and Public Assets

However, once you run npm run dev, you will notice that you get an error saying:

Error: > Couldn't find a pages directory. Please create one under the project root

So let’s create some pages. On the front page, we will have a logo and a button to navigate to the quotes. Create a new folder called pages in your root directory and add an index.js file:

Copied to clipboard! Playground
import Link from 'next/link'

const Index = () => (
    <>
        <img src="next.svg" alt="logo" />
        <div>
            <button>
                <Link href="/list">See quotes</Link>
            </button>
        </div>
    </>
);

export default Index;
index.js

As you can see, Next exposes a Link component that you can use for different routes. To navigate to /list, create a new file under the pages folder, called list.js. Whatever you name your components can be accessed through a slug in the browser. For now, just return an empty div.

Copied to clipboard!
const List = () => <>We will display the quotes here...</>;

export default List;
list.js

You may also noticed that we are referencing an image inside index.js. To add publicly available static assets, you want to create a public folder and add your images (or fonts) there.

How to add core HTML elements

As there is no index.html there’s no way at the moment to add meta tags or even customize the title for the page. Luckily, Next also has a built-in Head component that you can use just for this case. Under pages, create an _app.js file; this will act as an entry for the app:

Copied to clipboard! Playground
import Head from 'next/head'

const App = ({ Component, pageProps }) => (
    <>
        <Head>
            <title>Next quote</title>
            <link rel="icon" href="/favicon.ico" />
        </Head>
        <main>
            <Component {...pageProps} />
        </main>
    </>
);

export default App;
_app.js

Between the Head elements, you can add anything you would normally do. As by default, this file acts as an entry in Next.js, you also need to render every other component here. This is what you can see on line:10. You get both the Component and pageProps from the properties.

Looking to improve your skills? Check out our interactive course to master React from start to finish.
Master Reactinfo Remove ads

How to Style Your Pages

The page looks pretty boring at the moment, so let’s add some styles. In order to add CSS, you could use a style tag at the end of your components, like so:

Copied to clipboard! Playground
const Index = () => (
    <>
        <img src="next.svg" alt="logo" className="logo" />
        <div>
            <button>
                <Link href="/list">See quotes</Link>
            </button>
        </div>
    </>

    <style jsx>{`
        .logo { ... }
    `}</style>
);
index.js

However, this does not scale very much. Instead, Next supports CSS modules out of the box. Simply import your CSS then use your exported classes:

Copied to clipboard! Playground
import Button from '../components/Button'

import styles from '../css/index.module.css'

const Index = () => (
    <>
        <img src="next.svg" className={styles.logo} alt="logo" />
        <Button text="See quotes" link="list" />
    </>
);

export default Index;
index.js

For this, I’ve created a css folder next to pages and added a new file. Next supports CSS modules by using the [name].module.css naming, so make sure you name your files accordingly, otherwise you may run into errors.

Note that I’ve also created a components folder and outsourced the button into a custom Button component and added a couple of styles to it. This way you can reuse the buttons anywhere in the app with the same look and feel.

Now usually, you also want to introduce global styles to reset certain elements or give a basic outline to your app. To add global CSS, you need to import your CSS files through _app.js:

Copied to clipboard! Playground
import Head from 'next/head'

import '../css/base.css'

const App = ({ Component, pageProps }) => ( ... )

export default App;
_app.js

How to Fetch Data From an API

All that’s left to do, is to request some quotes from the server and display them. To do this, you want to make use of the getStaticProps function. This is a built-in function that Next uses to fetch data at build time. Inside your list.js file, after you’ve defined the component, also export this function:

Copied to clipboard! Playground
const List = () => <>We will display the quotes here...</>;

export const getStaticProps = async context => {
    const result = await fetch('https://type.fit/api/quotes');
    const quotes = await result.json();

    return {
        props: {
            quotes
        }
    }
}

export default List;
list.js

You can also pass a context to the function which contains various data about the page, such as route params or locales. For the full list of properties this object contains, you can refer to Next.js’ documentation.

This function needs to export an object with a props property that will be passed to your component. Anything you pass here will be available for use in your component. To display the quotes, change the body of the component to the following:

Copied to clipboard! Playground
import Quote from '../components/Quote'
import styles from '../css/list.module.css'
import inputStyles from '../css/input.module.css'

const List = ({ quotes }) => {
    return (
        <>
            <div className={inputStyles['input-container']}>
                <input className={inputStyles.input} placeholder="Filter by author" />
            </div>
            {quotes.map((quote, index) => (
                <div className={styles['quote-wrapper']} key={index}>
                    <Quote text={quote.text} author={quote.author} />
                    <span className={styles['quote-number']}>{`#${index + 1}`}</span>
                </div>
            ))}
        </>
    )
}

export const getStaticProps = async context => { ... }
list.js

It will get the quotes returned from the getStaticProps function. From line:9, I’ve added an input to let the user filter the quotes, and then mapped through them to display everything. Again, I’ve created a separate component for the Quote to make it reusable and imported a CSS to style everything.

To add the filtering functionality, you can add a new state with useState at the beginning of the component, like so:

Copied to clipboard! Playground
const List = ({ quotes }) => {
    const [filteredQuotes, updateQuotes] = useState(quotes);

    const filterQuotes = e => {
        const results = filteredQuotes.filter(quote => quote.author && quote.author.toLowerCase().startsWith(e.target.value.toLowerCase()))

        updateQuotes(results);
    }

    return (
        <>
            <div className={inputStyles['input-container']}>
                <input className={inputStyles.input} placeholder="Filter by author" onKeyUp={filterQuotes} />
            </div>
            {filteredQuotes.map((quote, index) => (
                <div className={styles['quote-wrapper']} key={index}>
                    <Quote text={quote.text} author={quote.author} />
                    <span className={styles['quote-number']}>{`#${index + 1}`}</span>
                </div>
            ))}
        </>
    )
}
list.js

This will filter the quotes based on what you write into the input. Make sure you also attach the function to the onKeyUp prop of the input, as well as change quotes.map to filteredQoutes.map on line 15.

Using the app created by Next.js

Conclusion

And now you have a working application written in React, rendered on the server with Next.js. Overall, Next.js is a great choice if you want to render your React application on the server-side. One common use-case is using it as a static site generator for blogs, galleries or portfolios. Make sure to have a look at the showcase page on Next.js, to see which big sites are using it.

undefined

I have the whole application hosted on GitHub, with CSS and components included that are not covered in this tutorial. You can clone it from the link below.

clone the project from GitHub

Do you have any experience with Next.js? Let us know your thoughts about it in the comments below. Thank you for reading through, happy coding!

  • twitter
  • facebook
React
Did you find this page helpful?
📚 More Webtips
Mentoring

Rocket Launch Your Career

Speed up your learning progress with our mentorship program. Join as a mentee to unlock the full potential of Webtips and get a personalized learning experience by experts to master the following frontend technologies:

Courses

Recommended

This site uses cookies We use cookies to understand visitors and create a better experience for you. By clicking on "Accept", you accept its use. To find out more, please see our privacy policy.