NextJS: A Beginner Guide
Getting started
Create a new nextjs project
npx create-next-app@latest
Give a project name and accept default value. To run the project run
npm run dev
Routing
- All routes must be placed inside the app folder
- Every file that corresponds to the route must be named
page.jsx
orpage.tsx
- Each folder corresponds to the path segment in the browser URL
For the home page route in a folder app
create a file name page.tsx
export default function Home() {
return (<h1>
This is home page!
</h1>);
}
layout.tsx
file is for nav bar and footer which can be shared in all the pages of the app. In layout.tsx
file
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>
<header>This is header of the page</header>
{children}
<footer>This is footer of the page</footer>
</body>
</html>
)
}
To create a route /about
we need to create a folder named about
inside app
folder and create a file name page.tsx
in about
folder. This will be the route for /about
const About = ()=>{
return <>
<h2>This is about page!</h2>
</>
}
export default About;
Nested Routing
Nested route such as /blog
, /blog/first
and /blog/second
to achieve this routes:
for that we can create a folder named blog
and create a page.tsx
file for /blog
route
for /blog/first
we can create another folder named first
inside blog
folder and create a file page.tsx
same for /blog/second
. Create a folder inside blog
folder named second
and create a page.tsx
file in that second
folder.
If you want a layout that cover all routes start from /blog/*
then you can create a layout.tsx
file inside blog
folder and following code goes in that file:
import Link from "next/link"
export default function BlogLayout({
children,
}: {
children: React.ReactNode
}) {
return <section>
<div style={{display:"flex", justifyContent: "flex-start", gap:"2rem"}}>
<Link href="/blog/first">
First blog
</Link>
<Link href="/blog/second">
Second blog
</Link>
</div>
{children}</section>
}
Dynamic Route
Dynamic route such as /products/productId
where productId
will be dynamic and based on the productId
the page will show the product detail of that specific product. To create such a route let's create a route /products
where list of the products will be displayed and when user click on specific product it will trigger the /products/productId
route and show the detail of that particular product. Create a folder named products
and inside that folder create a file named page.tsx
and following code goes in that file:
import Link from "next/link";
export default function Products() {
const productList = [
{
name: "product1",
id: 1,
},
{
name: "product2",
id: 2,
},
{
name: "product3",
id: 3,
},
{
name: "product4",
id: 4,
},
];
return (
<>
{" "}
<div
style={{ display: "flex", justifyContent: "flex-start", gap: "2rem" }}
>
{productList.map((product) => {
return (
<Link key={product.id} href={`/products/${product.id}`}>
{product.name}
</Link>
);
})}
</div>
</>
);
}
Now, inside products
folder create another folder named [productId]
and inside that folder create page.tsx
file. this folder will be dynamic which holds dynamic productId
. In page.tsx
file following code goes:
type Prop = {
params: { productId: number };
};
type Product = {
id: number;
detail: string;
};
const productDetail = [
{
id: 1,
detail: "This is the detail of product 1",
},
{
id: 2,
detail: "This is the detail of product 2",
},
{
id: 3,
detail: "This is the detail of product 3",
},
{
id: 4,
detail: "This is the detail of product 4",
},
];
export default async function ProductDetail({ params }: Prop) {
const { productId } = await params;
const product = productDetail.find(
(product) => product.id === Number(productId)
);
return (
<>
{product ? (
<h2>{product.detail}</h2>
) : (
<h2>Product detail could not be found !</h2>
)}
</>
);
}
Catch-all segments and Optional Catch-all segments
If we want to achieve a route such as /docs/concept1/exapmle1
or /docs/concept2/example1/feature1
, we can use Catch-all segments
. For that we need to put folder name inside [...slug]
or for Optional Catch-all segments
inside [[...slug]]
. Now, let's create a folder docs
and inside that folder let's create another folder name [[...slug]]
. Here we will be doing Optional catch-all segments
. Let's create a file page.tsx
inside that folder.
import Link from "next/link";
export default function Docs({ params }: { params: { slug: string[] } }) {
let contain: string;
const getURLPath = (slugArray: string[], index = 0): string => {
if (index >= slugArray.length) return "";
return `/${slugArray[index]}/ ${getURLPath(slugArray, index + 1)}`;
};
if (!params?.slug?.length) {
contain = "This is Document page";
} else {
contain = `This is about: docs/${getURLPath(params.slug)}`;
}
return (
<>
<h3>{contain}</h3>
</>
);
}
In above code, we get convert the slugs into URL using getURLPath
function and display the URL.