How should dynamic route pages be properly managed in NextJS?

Working on my first project using NextJS, I'm curious about the proper approach to managing dynamic routing.

I've set up a http://localhost:3000/trips route that shows a page with a list of cards representing different "trips":

https://i.stack.imgur.com/8o9td.png

When clicking on one of these cards, I want to navigate to a dynamic page for that specific trip, such as

http://localhost:3000/trips/0b68a50a-8377-4720-94b4-fabdabc12da1

This is my folder structure:

https://i.stack.imgur.com/87Cn4.png

We already have the dynamic routes set up and they are functioning properly.

The TripCard component represents each card. The TripComponent displays a grid of TripCards. trips/index.tsx contains the TripsComponent (along with other UI components).

Currently, I handle the dynamic route in TripCard as follows:

import { Trip } from './Models'
import { useRouter } from 'next/router'

const TripCard = ({ trip }: { trip: Trip }) => {
    const router = useRouter()
    return (
        <div className="card bg-base-100 shadow-xl hover:bg-gray-100 active:bg-gray-300">
            <div className="card-body" onClick={() => router.push('/trips/' + trip.id)}>
                <h2 className="card-title">{trip.name}</h2>
                <p>This is a trip!</p>
            </div>
        </div>
    )
}

export default TripCard

The dynamic page [tripId].tsx looks like this:

import { NextPage } from 'next'
import { useRouter } from 'next/router'

const TripPage: NextPage = () => {
    const router = useRouter()
    const tripId = router.query.tripId
    return (
        <div>
            <h1>This is {tripId}</h1>
        </div>
    )
}

export default TripPage

And here's TripsComponent.tsx:

import { Trip } from './Models'
import TripCard from './TripCard'

const TripsComponent = ({ trips }: { trips: Trip[] }) => {
    return (
        <div>
            <div className="grid grid-cols-4 gap-4">
                {trips.map((trip: Trip) => (
                    <div>
                        <TripCard trip={trip}></TripCard>
                    </div>
                ))}
            </div>
        </div>
    )
}

export default TripsComponent

And trips/index.tsx:

import axios from 'axios'
import { GetStaticProps, InferGetStaticPropsType, NextPage } from 'next'
import { Trip } from '../../components/Models'
import TripsComponent from '../../components/TripsComponent'

const TripsPage: NextPage = (props: InferGetStaticPropsType<typeof getStaticProps>) => {
    return (
        <div className="m-9">
            <h1 className="mt-9 text-3xl font-bold text-slate-800">Your Trips</h1>
            <div className="justify-end">
                <button className="btn btn-primary">Add Trip</button>
            </div>
            <div className="divider"></div>
            <TripsComponent trips={props.data} />
        </div>
    )
}

export const getStaticProps: GetStaticProps = async () => {
    // fetches data and passes to props
}

export default TripsPage

My concern is about the best practice for handling routing where cards lead to dynamic URLs with associated pages. Currently, in TripCard, I have a hardcoded router.push:

<div className="card-body" onClick={() => router.push('/trips/' + trip.id)}>

However, this method may not be the most efficient. For instance, what if I need to utilize TripCard in another view with a different route?

What would be the ideal way to organize code to achieve this functionality in NextJS?

Answer №1

If you're looking to pass the URL as props and utilize NextJs <Link/>, consider the following approach:

import { Trip } from './Models'
import { useRouter } from 'next/router'
import Link from 'next/link'

const TripCard = ({ trip, url }: { trip: Trip, url: string }) => {
    const router = useRouter()
    return (
        <div className="card bg-base-100 shadow-xl hover:bg-gray-100 active:bg-gray-300">
       <Link href={url} passHref>
            <div className="card-body">
                <h2 className="card-title">{trip.name}</h2>
                <p>This is a trip!</p>
            </div>
        </Link>
        </div>
    )
}

export default TripCard

To use the component, simply do:

<TripCard trip={trip} href={'/trips/' + trip.id}></TripCard>

I hope this solution works well for you.

Answer №2

When working with dynamic routes, it is important to utilize the getStaticPaths and getStaticProps functions to fetch and generate all necessary paths beforehand. By exporting getStaticPaths from the Next.js page, the platform will pre-render all specified paths.

The getStaicPaths function must return two values: paths and fallback. The paths property should consist of an array of parameters, while the fallback determines whether Next.js should search for pages to pre-render if they have not been pre-rendered before. For instance, creating a new card on a published site would trigger Next.js to look for the card in the database and pre-render it if the fallback is set to true. Otherwise, a 404 error will be displayed if the fallback is false.

Additionally, it is recommended to use the Link component instead of router.push for better navigation.

Find more information here

Answer №3

Your current routing setup is spot on. If you want to enhance it further, consider the following suggestions:

To access trips, navigate to /trips and for each individual trip, use the route /trip/<trip id>

If you wish to make the trip URL dynamic, pass the URL directly to the TripCard component.

The URL structure should be as follows:

<route name>/<trip id>

Implement this by using

 <TripCard trip={trip} url={url}></TripCard>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The timing of the JavaScript dialog with the AJAX call is off-kilter

Encountering an issue with a JavaScript script designed to showcase a JQUERY dialog box based on a C# ViewModel. Within a repeater, there is an ASP drop-down menu displaying 'Registration Date' details. The objective is for the JavaScript dialog ...

Troubleshooting Angularjs: Why isn't the HTML displaying the variable value?

Trying to display the value of an AngularJS variable in HTML using this code: <div ng-controller="MyTextbox"> <p>Last update date: {{nodeID1}} </p> Here's my angularjs controller code: angular.module("umbraco").controller("MyTex ...

Switch between parent elements in Angular JS Templates while preserving children elements

It seems like I'm overlooking a rather basic feature in a templating engine. Consider the following template: <a ng-if="icon.link" href="icon.link"> <i ng-class="['fa',icon.icon_class]"></i> </a> <span ng-if= ...

Observing the data retrieved from an AJAX request

Currently, I have this AJAX call in my code: $('#search').keyup(function() { $.ajax({ type: "GET", url: "/main/search/", data: { 'search_text': $('#search').val() }, suc ...

What is the best way to add animation to my `<div>` elements when my website is first loaded?

I am looking for a way to enhance the appearance of my <div> contents when my website loads. They should gradually appear one after the other as the website loads. Additionally, the background image should load slowly due to being filtered by the wea ...

Angular 6: Utilizing async/await to access and manipulate specific variables within the application

Within my Angular 6 application, I am facing an issue with a variable named "permittedPefs" that is assigned a value after an asynchronous HTTP call. @Injectable() export class FeaturesLoadPermissionsService { permittedPefs = []; constructor() { ...

What is the best way to add multiple elements to an array simultaneously?

I am facing an issue with my array arrayPath. I am pushing multiple values into it, but there are duplicates in the data. When the value of singleFile.originalFilename is a duplicate, I do not want to push that duplicate value into arrayPath. How can I ach ...

Passing parameters to an external function in order to display a message is proving difficult. An error of type TypeError is being encountered, specifying that the Class constructor AlertMessage cannot be called without using the

Every time I attempt to pass a message as an argument to the showAlert() function, an error is triggered: Error: An instance of the AlertMessage class cannot be created without using 'new' image: I am simply trying to send the message as a para ...

Navigational Drop-down Menu - Utilizing Next.js and Tailwind CSS

Currently, I'm tackling a project that requires me to implement a dropdown menu using tailwind CSS and Next.js. Would be incredibly thankful if someone could provide me with a sample code for this feature. ...

What is the best way to clear a form in a Next.js 13.4 component following a server action?

Currently, I am working on a component using next.js 13.4, typescript, and resend functionality. My code is functioning properly without clearing data from inputs, as it uses the "action" attribute which is commented out. However, I started incorporating ...

Instructions on deactivating the background when the sidebar is displayed and closing the sidebar by clicking anywhere other than the sidebar

I'm in the process of creating a sidebar for my website. When the sidebar is displayed (by clicking showRight), I want to disable the background content so that the user can't interact with anything outside of the menu. If the user clicks on th ...

Creating a Dual Y-Axis Chart with Two Sets of Data in chart.js

I utilized the chart.js library to write the following code snippet that generated the output shown below. My primary concern is how to effectively manage the labels on the horizontal axis in this scenario. CODE <!DOCTYPE html> <html lang="en"& ...

Transitioning from Jquery to vanilla JavaScript or transforming Jquery code into pseudo code

Struggling with a snippet of jQuery code here. While I have a good grasp on JavaScript, my knowledge of jQuery is somewhat limited. I am seeking assistance to analyze the following code in order to translate it into plain JavaScript or pseudo code that ca ...

Add an element to the parent body from an iframe with this easy tutorial!

Within the iframe, I have the following code snippet. <script type="text/javascript"> $(document).ready(function(){ $("body").append($("#ctap").html()); }); </script> I am looking to append the HTML content of #ctap to the par ...

After integrating session store into my application, nestjs-sequelize is not synchronizing with any models

I'm currently working on developing a Discord bot along with a website dashboard to complement it. Everything is running smoothly, except for the backend Nestjs API that I am in the process of creating. I decided to use Sequelize as the database for m ...

External CSS File causing improper sizing of canvas image

I have been working on implementing the HTML5 canvas element. To draw an image into the canvas, I am using the following javascript code: var img = new Image(); var canvas = this.e; var ctx = canvas.getContext('2d'); img.src = options.imageSrc; ...

What are the best ways to keep a django page up to date without the need for manual

Currently, I am in the process of developing a Django website focused on the stock market. Utilizing an API, I am pulling real-time data from the stock market and aiming to update the live price of a stock every 5 seconds according to the information pro ...

Encountered an issue with resolving the module specifier while attempting to import a module

Whenever I attempt to import a module, I consistently encounter this error message Failed to resolve module specifier "mongodb". Relative references must start with either "/", "./", or "../". and I have searched ext ...

Intercepting the K-pager navigation with a pop-up modal for user confirmation before switching to a different page

Scenario Currently, I have developed a WebApp using kendo, bootstrap, and backbone. One of the key features is a grid that showcases data pulled from a database. This grid has a data source binding with serverPaging enabled. Data Source Configuration al ...

What is the best method for managing file storage and retrieval in web applications that only run on the client-side?

I'm currently working on an application where users can create their own data. Without a backend or database, all the information is stored within the user's session. My preferred solution involves: User interacts with the app, clicks "Save", ...