I've composed this guide to give you a practical overview of perhaps the most important React library you will use to build 90% of your projects: Next.js.
The goal of this tutorial is to get you started using Next.js as easily as possible.
This is not a complete guide on Next, but it will give you everything you need to understand:
Let's dive in!
The ultimate tool for any React developer to learn and improve their own projects is, without a doubt, Next.js.
The NextJS.org Homepage
Whether I'm building a static site with interactivity like a blog, or a highly dynamic, full-stack project like a social media app, I almost always reach for Next.
The first reason for you to use Next is, as the banner headline states, because it's a React framework.
Think of it as a "batteries-included" way to build your React applications, which gives you the simplicity of tools like Create React App, combined with a suite of other super powerful features.
Despite being a framework, Next.js keeps some of the React philosophy of being unopinionated. Next gives you features to improve your overall development experience but doesn't constrain the amount of options you can choose from.
In fact, given what Next makes possible for React apps, I would contend that it has really expanded the number of options available to you, if you need it.
You can get a more complete sense of everything Next.js apps are capable of by checking 100s of example Next.js projects at
:
Next.js Examples
There you can find examples on how to create the following Next (React) apps:
And tons more! Be sure to check out the full list to spark your imagination.
Below is a shortlist of what Next gives your React projects.
In short, it provides the functionality of an entire suite of packages within a single next
dependency.
Next.js gives you:
Additionally there are many essential things that Next.js does not provide out of the box.
For example, there is no built-in way to do the following in Next:
covers these shortcomings, but it is important to note that while Next.js gives you a great deal it will not alone cover every app use-case.
I'll give you the highlights of Next.js to give you a sense of how the framework gives you great defaults that make you more productive.
If you have NPM installed, start any new Next project with the command:
npx create-next-app my-next-project
create-next-app
is a package like Create React App, but for Next.js projects.
In short, it gives us a Next project with all its dependencies installed (which are next
, react
, and react-dom
) plus some dummy pages and styles.
You currently find four main scripts listed in your package.json file:"scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint" }
dev
– runs a development server on localhost:3000build
– creates a built application ready for deploymentstart
– starts your built Next application (must run next build
first)lint
– will "lint" your Next project using the dev dependency ESLint to warn you if your written code needs to be fixedTo run your Next project in development, make sure you are in your project folder (my-next-project) and run the dev script:
npm run dev
After your project is up and running on localhost:3000, navigate there and you should see a default app:
Index page of Create-Next-App project
Want to add TypeScript? Couldn't be easier:
# run 'touch' to create an empty config file # Next will auto-populate it touch tsconfig.json # then you'll be prompted to run the command: npm install -D typescript @types/react @types/node # now you can use TypeScript everywhere ✨
Want to add an About page to your app?
Just drop your component in /pages/about.js (.tsx if you're using TypeScript):
// No React import needed up here! 😳 export default function About() { return <div>About</div> }
And it works!
This is a great advantage because we no longer have to install a library like React Router that requires boilerplate such as a Router and Route component, among others.
If you would like dynamic pages, which are in the same folder but have different slugs (such as blog posts), Next allows us to render the same page component by wrapping the filename in brackets.
For example, to display blog posts according to a particular slug, we could drop a "blog" folder in pages with the filename: [slug].js:
import { useRouter } from 'next/router' // if we navigate to localhost:3000/blog/123... export default function BlogPost() { const router = useRouter() const { slug } = router.query return <p>Post: {slug}</p> // ...you'll see "Post: 123" }
Next conveniently exposes a useRouter
React hook to make accessing information about the app location or history very easy.
In this example, it allows us to get the query parameters (the dynamic value) from router.query
. The property name slug
matches the dynamic name we gave our file: [slug].js
.
Note: You can have multiple query parameters due to using nested folders with dynamic names. Such as /blog/[topic]/[slug].js. From within [slug].js, we could access both thetopic
andslug
query params.
Just as Next includes routes and routing, the framework also gives us a helpful Link
component from next/link
.
It may look a bit unusual if you are coming from React Router, because it requires placing a traditional anchor tag link as a child and passing the href as a prop.
If we wanted to link to the home page (/) and a blog route (i.e. /blog/123), we would include the following in /pages/about.js:
import Link from "next/link"; export default function About() { return ( <div> <h1>About Me</h1> <div> <Link href="/"> <a>Home</a> </Link> <Link href="/blog/123"> <a>My Blog Post</a> </Link> </div> </div> ); }
href
is the only required prop for the Link
component and data can be passed to it as an object as well:
import Link from "next/link"; export default function About() { return ( <div> <h1>About Me</h1> <div> <Link href={{ pathname: "/about" }}> <a>Home</a> </Link> <Link href={{ pathname: "/blog/[slug]", query: { slug: "123" }, }} > <a>My Blog Post</a> </Link> </div> </div> ); }
Route changes can also be done using the useRouter
hook, primarily using the .push()
method to push to a different route programmatically.
Here is a dummy example of a login page where a user provides their email to login and is pushed to the '/verify-email' route afterwards.
export default function Login() { const router = useRouter() function onSubmit(event) { event.preventDefault(); const email = event.target.elements.email.value; await sendLoginEmail(email); // push user to /verify-email page router.push('/verify-email'); } return ( <div> <h1>Log in here</h1> <form onSubmit={onSubmit}> <input name="email" placeholder="Your email address" /> <button type="submit">Submit</button> </form> </div> ); }
Pages in web applications not only need data within the HTML body, but meta (head) tags as well.
In a Create React Application, this would require installing an external dependency called React Helmet.
In Next, we can use the Head
component from next/head
to conveniently add meta data to our webpages to be shown in search results and embeds:
import Link from "next/link"; import Head from "next/head"; export default function About() { return ( <div> <Head> <title>About | My Cool Site</title> <meta name="description" content="You really need to read this website because it's made with Next.js" /> </Head> <h1>About Me</h1> <div> <Link href="/"> <a>Home</a> </Link> <Link href="/blog/123"> <a>My Blog Post</a> </Link> </div> </div> ); }
Note: The Head component should be included within any page component, usually right within the opening tag. You can create a reusable Head component that accepts dynamic values via props.