Learn Nextjs Part 1: Installation, Pages, Layout, Links, Routes, Loading, Error & Route handler === ![](https://i.imgur.com/OZaVMD1.png) --- ###### tags: `Nextjs`, `react` ## Installation Open terminal and enter this command :`npx create-next-app@latest --experimental-app` It will ask several questions for installing relevant packages. ![](https://i.imgur.com/xQBl6Gy.png) After that, it will start installing. ![](https://i.imgur.com/4kJyiil.png) Here is the basic file structure. ```json ├── .eslintrc.json ├── .gitignore ├── app │ ├── api │ │ └── hello │ │ └── route.ts │ ├── favicon.ico │ ├── globals.css │ ├── layout.tsx │ ├── page.module.css │ └── page.tsx ├── next-env.d.ts ├── next.config.js ├── package-lock.json ├── package.json ├── public │ ├── next.svg │ ├── thirteen.svg │ └── vercel.svg ├── README.md └── tsconfig.json ``` - `app` folder is where all the routes and pages located - `api` folder is where all api calls located. - `public` is where all static files, such as svg, png .etc located. Run `npm run dev` to start next server. ![](https://i.imgur.com/Vcz9HIl.png) ![](https://i.imgur.com/KE5bDm1.png) ## Routing Fundamentals > Reference: > [Nextjs-Routing Fundamentals](https://beta.nextjs.org/docs/routing/fundamentals) ![](https://i.imgur.com/YRX2nQl.png) - Tree: A component tree with parent and children components, a folder structure, etc. - Subtree: Part of a tree, starting at a new root (first) and ending at the leaves (last). - Root: First node in a tree or subtree. - Leaf: Nodes in a subtree that have no children. ![](https://i.imgur.com/HXBsCaj.png) - URL Segment: Part of the URL path delimited by slashes. - URL Path: Part of the URL that comes after the domain (composed of segments) > Reference > [Project Setup](https://nextjs.org/docs#automatic-setup) ## Creating Routes We can define routes inside `app` directory, here's the steps: 1. Go inside `app` directory. 2. Create a folder, folder refers to a route, i.e. `about` folder, `product` folder, each of them represent a **route segment**. 3. Create a subfolder inside the `about` folder as this would be **nested route**. ```json app/ ┣ about/ (about route) ┃ ┗ team/ (nested route) ┣ api/ ┃ ┗ hello/ ┃ ┗ route.ts ┣ product/ (product route) ┣ favicon.ico ┣ globals.css ┣ layout.tsx ┣ page.module.css ┗ page.tsx ``` ### page Inside each route folder, it would have a `page.js`(or `ts`, `jsx`, `tsx`), this makes route segment publicly accessible. ```json app/ ┣ about/ ┃ ┣ team/ ┃ ┃ ┗ page.tsx (this page contains team content) ┃ ┗ page.tsx (this page contains about content) ┣ api/ ┃ ┗ hello/ ┃ ┗ route.ts ┣ product/ ┃ ┗ page.tsx (this page contains product content) ┣ favicon.ico ┣ globals.css ┣ layout.tsx ┣ page.module.css ┗ page.tsx (this page is the root) ``` ### Route Groups Sometimes we might need to break out of the routes without affetcing it, we can create a **route group**, it is used: - Organize routes without affecting the URL structure. - Opting-in specific route segments into a layout. - Create multiple root layouts by splitting your application. Using parenthesis as a naming convention, e.g. `(marketing)` ```json app/ ┣ (blog)/ ┃ ┗ layout.tsx ┣ (marketing)/ ┃ ┗ layout.tsx ┣ about/ ┃ ┣ team/ ┃ ┃ ┗ page.tsx ┃ ┗ page.tsx ┣ api/ ┃ ┗ hello/ ┃ ┗ route.ts ┣ product/ ┃ ┗ page.tsx ``` Even though `(marketing)` and `(blog)` share the same URL hierarchy, we can create a different layout by adding `layout.tsx` inside of it. We can move route inside a route group, in this way, they can share the same layout, any routes that outside of the group will not share the layout. ```json app/ ┣ (blog)/ ┃ ┗ layout.tsx ┣ (marketing)/ ┃ ┗ layout.tsx ┣ about/ ┃ ┣ team/ ┃ ┃ ┗ page.tsx (it's inside of marketing folder, it can have same layout ) ┃ ┗ page.tsx (it's inside of marketing folder, it can have same layout ) ┣ api/ ┃ ┗ hello/ ┃ ┗ route.ts ┣ product/ ┃ ┗ page.tsx ``` ### Dynamic Segments Using square brackets for refering dynamic segments, e.g. `[slug]`. They are passed as the `params` props. Let's say we have a `blog` route, usually it will have ids or identifiers for each post, e.g. `/blog/1`, `/blog/2`, we can create a `[slug]` folder inside the `blog` folder. #### Catch-all segments Using ellipsis inside the brackets, e.g. `[...slug]`, `[...folderName #### Optional catch-all segments Using double square brackets, e.g.`[[...folderName]]` ## Root layout & Multiple Root layouts **Layouts** preserve state, interactivity and do not re-render, some important points we need to know: - Must contains `<html>` and `<body>` tag. - They are **Server Component** by default. - They can fetch data. - It's impossible to pass data between a parent layout to its children. - `layout.tsx` will wrap the `page.tsx` Root layout refers to some components that can be apply multiple route, e.g. `navbar` or `footer`, below you can see the navbar is at a nested route `about/team`, some important points we need to know: - `app` directory **MUST** include a root layout. - Can use the built-in SEO support to manage `<head>` HTML element. ![](https://i.imgur.com/qAB6xCW.png) ```json app/ ┣ (blog)/ ┃ ┗ layout.tsx ┣ (marketing)/ ┃ ┗ layout.tsx ┣ about/ ┃ ┣ team/ ┃ ┃ ┗ page.tsx ┃ ┗ page.tsx ┣ api/ ┃ ┗ hello/ ┃ ┗ route.ts ┣ product/ ┃ ┗ page.tsx ┣ favicon.ico ┣ globals.css ┣ layout.tsx (root layout that applies to every route) ┣ page.module.css ┗ page.tsx ``` We can create **Multiple Root layouts** by removing the top-level `layout.tsx`, and adding `layout.tsx` file inside each route groups, this allows us to have a completely different UI, but it needs to have `<html>` and `<body>` tag. > Reference > [Defining Routes](https://beta.nextjs.org/docs/routing/defining-routes) ### Component Hierarchy - `layout.js` - `template.js` - `error.js` (React error boundary) - `loading.js` (React suspense boundary) - `not-found.js` (React error boundary) - `page.js` or nested `layout.js` ![](https://i.imgur.com/vv2e4EW.png) ### Nestd Component Hierarchy ![](https://i.imgur.com/Sz2Of3X.png) ## Linking & Navigating In nextjs, router uses **server-centric** routing with **client-side navigation. Two ways to navigate between routes: 1. `<Link>` component. 2. `useRouter` hook. ### `<Link>` Component It provides prefetching and client-side navigation, it's the primary way to navigate between routes. ```typescript= // In React, <Link> is from react-router-dom import { Link } from 'react-router-dom'; export default function Nav() { return ( <nav> <Link to="/">Logo</Link> </nav> ) } ``` ```typescript= // In Nextjs export default function Page() { return <Link href="/dashboard">Dashboard</Link>; } ``` ## Loading To show an instant loading state, this would help to create loading UI with `React Suspense`. ```typescript= // loading.tsx export default function Loading() { return <LoadingSkeleton /> } ``` In the same folder, `loading.tsx` will be nested inside `layout.tsx`, it will wrap the `page.tsx` and any children below in a `<Suspense>`. ![](https://i.imgur.com/xYbWYrH.png) 1. Navigation is immediate, even with **server-centric routing**. 2. Navigation does not need to wait for the content of the route to fully load before navigating to another route. 3. Shared layouts remain interactive. ### Manually Defining Suspense Boundaries We can still manually create Suspense bundaries, but it's recommended to use `loading.tsx` convention as Nextjs optimizes. > Reference: > [Linking & Navigating](https://beta.nextjs.org/docs/routing/linking-and-navigating) > [Loading UI](https://beta.nextjs.org/docs/routing/loading-ui) ## Error ```typescript= // error.tsx 'use client'; export default function Error({ error, reset, }: { error: Error; reset: () => void; }) { return ( <div> <h2>Something went wrong!</h2> <button onClick={() => reset()}>Try again</button> </div> ); } ``` `error.tsx` allows to handle runtime errors in nested routes. Same as [React Error Boundary](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary), it will: - Automatically wrap a route segment and its nested children. - Isolate errors to protect the whole app being crushed when there's an error. - Attempt to recover from an error without a full page reload. **Error components must be Client components** ![](https://i.imgur.com/mRswFJs.png) - Export `error.tsx` file, as it's used as the fallback component. - If the error is thrown within the boundary, the error is contained and the fallback component is rendered. - When the error component is active, **layouts above it maintain their state and remain interactive**. ### `reset()` Use the `reset()` to prompt the user to attemp to reocver from the error, when it executes, it will try to re-render the error boundary's content.