From React to Next.js

Getting Started with Next.js

To add Next.js to your project, you will not need to load the react and react-dom scripts from unpkg.com anymore. Instead, you can install these packages locally using the Node Package Manager: npm.

Note: You will need to have Node.js installed on your machine (minimum version requirement), you can download it here.

To do so, create a new file called package.json with an empty object {}.

// package.json
{
}

In your terminal, run npm install react react-dom next. Once the installation is complete, you should be able to see your project dependencies listed inside your package.json file:

// package.json
{
  "dependencies": {
    "next": "^12.1.0",
    "react": "^17.0.2",
    "react-dom": "^17.0.2"
  }
}

You will also notice a new folder called node_modules that contains the actual files of our dependencies.

Jumping back to the index.html file, you can delete the following code:

  1. The react and react-dom scripts since you’ve installed them with NPM.
  2. The <html> and <body> tags because Next.js will create these for you.
  3. The code that interacts with app element and ReactDom.render() method.
  4. The Babel script because Next.js has a compiler that transforms JSX into valid JavaScript browsers can understand.
  5. The <script type="text/jsx"> tag.
  6. The React. part of the React.useState(0) function

After deleting the lines above, add import { useState } from "react" to the top of your file. Your code should look like this:

// index.html
import { useState } from 'react';
function Header({ title }) {
  return <h1>{title ? title : 'Default title'}</h1>;
}

function HomePage() {
  const names = ['Ada Lovelace', 'Grace Hopper', 'Margaret Hamilton'];

  const [likes, setLikes] = useState(0);

  function handleClick() {
    setLikes(likes + 1);
  }

  return (
    <div>
      <Header title="Develop. Preview. Ship. 🚀" />
      <ul>
        {names.map((name) => (
          <li key={name}>{name}</li>
        ))}
      </ul>

      <button onClick={handleClick}>Like ({likes})</button>
    </div>
  );
}

The only code left in the HTML file is JSX, so you can change the file type from .html to .js or .jsx.

Now, there are three more things you need to do to fully transition to a Next.js app:

  1. Move the index.js file to a new folder called pages (more on this later).
  2. Add default export to your main React component to help Next.js distinguish which component to render as the main component of this page.
   // ...
   export default function HomePage() {
   //  ...
  1. Add a script to your package.json file to run the Next.js development server while you develop.
   // package.json
   {
    "scripts": {
        "dev": "next dev"
    },
     // "dependencies": {
     //   "next": "^11.1.0",
     //   "react": "^17.0.2",
     //   "react-dom": "^17.0.2"
     // }
   }

Running the development server

To confirm everything works, you can view your app by running npm run dev inside your terminal and navigating to localhost:3000 in the browser. Then, make a small change to the code and save it.

Once you save the file, you should notice the browser automatically updates to reflect the change.

This feature is called Fast Refresh. It gives you instantaneous feedback on any edits you make and comes pre-configured with Next.js.

To recap, your code went from this...

<html>
  <body>
    <div id="app"></div>

    <script src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

    <script type="text/jsx">
      const app = document.getElementById("app")

      function Header({ title }) {
        return <h1>{title ? title : "Default title"}</h1>
      }

      function HomePage() {
        const names = ["Ada Lovelace", "Grace Hopper", "Margaret Hamilton"]
        const [likes, setLikes] = React.useState(0)

        function handleClick() {
          setLikes(likes + 1)
        }

        return (
          <div>
            <Header title="Develop. Preview. Ship. 🚀" />
            <ul>
              {names.map((name) => (
                <li key={name}>{name}</li>
              ))}
            </ul>

            <button onClick={handleClick}>Like ({likes})</button>
          </div>
        )
      }

      ReactDOM.render(<HomePage />, app)
    </script>
  </body>
</html>

...to this:

import { useState } from 'react';

function Header({ title }) {
  return <h1>{title ? title : 'Default title'}</h1>;
}

export default function HomePage() {
  const names = ['Ada Lovelace', 'Grace Hopper', 'Margaret Hamilton'];
  const [likes, setLikes] = useState(0);

  function handleClick() {
    setLikes(likes + 1);
  }

  return (
    <div>
      <Header title="Develop. Preview. Ship. 🚀" />
      <ul>
        {names.map((name) => (
          <li key={name}>{name}</li>
        ))}
      </ul>

      <button onClick={handleClick}>Like ({likes})</button>
    </div>
  );
}

On the surface, this is a small reduction in lines of code, but it does help highlight something: React is a library that provides essential primitives for building modern interactive UI. But there is still some work involved to combine that UI you create into an application.

Looking at the migration, you may already be getting a sense of the benefits of using Next.js. You removed the babel script, a taste of the complex tooling configuration you no longer have to think about. You also saw Fast Refresh in action, just one of the many developer experience features you can expect with Next.js.