What is the best way to incorporate client and server components in nextJS when params and query parameters are required?

I'm having difficulty understanding the client/server component concept in nextJS 14 (using app router).

Below is an example page illustrating how I typically structure it and what components are required:

  • I need to extract the id value from params
  • I need to execute a graphql query to fetch the data based on that id
    • This requires me to handle loading and error states accordingly
  • Finally, return the component with the retrieved data

Can someone demonstrate how to break this down into correct parts? The challenge lies in using metadata on the server side while running useParams() on the client. The separation of client/server functionalities has left me confused, so it would greatly benefit me to see the correct implementation.

app/presentation/[id]/page.tsx

'use client' // added because of useParams()

export const metadata: Metadata = { // needs to be on server
  title: 'Presentation'
}

export default function PresentationPage() {
  const params = useParams()
  const id = params?.['id']
  if (!id) throw new Error('Query parameter missing')
  if (Array.isArray(id))
    throw new Error("Query parameter shouldn't be an array")

  const { loading, data } = 
    usePresentationContentQuery({
      variables: {
        param: { name: 'id', value: id }
      }
    })

  if (loading) return <CircularProgress />
  if (data?.presentationContent == null)
    return (
      <Alert severity="error" elevation={0}>
        Missing data
      </Alert>
    )

  return (
    <Presentation data={data.presentationContent} />
  )
}

Answer №1

I usually convert all my page.tsx files into server components that pass parameters to their child components. While not mandatory, this approach is easy to remember and adds some organization.

In your situation, take out the 'use client' directive from the page.tsx file and include the params prop. Here's how you can do it:

export const metadata: Metadata = { // should be in the server
  title: 'Presentation'
}

export default function PresentationPage({params}:{
  params: { id: string }
}) {
  const id = params.id;
  if (!id) throw new Error('Query parameter missing')
  if (Array.isArray(id))
    throw new Error("Query parameter shouldn't be an array")

  return (<Body id={id} />)
}

Next, create a separate Body.tsx file where you can place the client-side code:

'use client'

export default function Body({id} : {id: string}) {
const { loading, data } = 
    usePresentationContentQuery({
      variables: {
        param: { name: 'id', value: id }
      }
    })

  if (loading) return <CircularProgress />
  if (data?.presentationContent == null)
    return (
      <Alert severity="error" elevation={0}>
        Missing data
      </Alert>
    )

  return (
    <Presentation data={data.presentationContent} />
  )
}

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

Remembering previous scroll position with jScroll upon revisiting page

I'm implementing infinite scrolling of products on our site using jQuery jScroll. Can anyone guide me on how to save the scroll position when the user returns to the homepage? Appreciate any assistance! ...

steps to initiate re-render of rating module

My first experience with React has been interesting. I decided to challenge myself by creating a 5-star rating component. All logs are showing up properly, but there seems to be an issue with the component not re-rendering when the state changes. Thank you ...

Is there a way for me to determine if something is hidden?

My goal is to have selector B toggle when selector A is clicked or when clicking outside of selector B. This part is working fine. However, I'm struggling with preventing selector B from toggling back unless selector A is specifically clicked - not w ...

Error Uploading File - Functioning in Postman but not on website interface

I'm currently pursuing the full stack certification on devchallenges.io and tackling the authentication app challenge. So far, I've successfully implemented the login and register functionality, as well as fetching the logged-in user's infor ...

Is it possible to access the operating system's native emoji picker directly from a website?

While there are numerous javascript plugins and libraries available for allowing users to select emojis for text inputs, both Windows and Mac operating systems already have their own native emoji pickers accessible via ⊞ Win. or CTRL⌘Space. Is there a ...

Using JavaScript and jQuery to create a delay when handling input events

I am working on a project where I have an HTML table that retrieves its values from a database using jQuery Ajax. Here is an example: <div id="tableId"></div> Below is the JavaScript code: function showUser(rowsToShow) { request = $.get("s ...

Discover the best method for retrieving or accessing data from an array using Angular

In my data processing task, I have two sets of information. The first set serves as the header data, providing the names of the columns to be displayed. The second set is the actual data source itself. My challenge lies in selecting only the data from th ...

Using Ajax to call a PHP function within a WordPress website

I am looking to trigger a PHP function using AJAX. Below is the code snippet of my form: <form class="woocommerce-form woocommerce-form-login login" method="post"> <p class="woocommerce-form-row woocommerce-form-row--wide form-row form-ro ...

The property 'enabled' is not a standard feature of the 'Node' type

Within the code snippet below, we have a definition for a type called Node: export type Node<T> = T extends ITreeNode ? T : never; export interface ITreeNode extends TreeNodeBase<ITreeNode> { enabled: boolean; } export abstract class Tre ...

Exploring the depths of Master-Detail functionality with Ionic and Angular, unlocking nested

Hey there! I'm currently working on a project using Ionic and Angular, where users can view events and see all the attending participants along with their information. To achieve this, I implemented a master-detail pattern within another master-detail ...

Glitch Uncovered in Excel Spreadsheet I Exported

I have a situation where I am working with an HTML table that includes both text and radio buttons. The issue arises when I attempt to export the table data along with the selected radio button values to Excel using the 'Export to Excel' button. ...

Error: [$injector:unpr] Oh no! The AuthServiceProvider Angular Service seems to be MIA

I am currently working on a small AngularJS project and encountering an issue with my service files not being successfully injected into the controllers. I have double-checked for any syntax errors, but despite trying different variations, the problem pers ...

Error in Displaying Vuetify Child Router View

I am currently working on integrating a child router-view to be displayed alongside surrounding components. Here is an overview of my routing setup: { path: "/login", name: "TheLoginView", component: TheLoginView, }, { path: "/dashboa ...

Developing a sliding menu with AngularJS

Currently, I am developing an AngularJS application. One of the features I am working on involves having a menu at the top of my page that, when an item is selected, will slide down to reveal content specific to that selection in the same area as the menu. ...

Creating effective test cases for Angular JS controllers

Our team has recently taken on the task of writing test cases for our application, specifically focusing on controllers. Utilizing Mocha, Chai, and Sinon libraries, we are looking for guidance on how to effectively write these test cases. We have shared a ...

Utilizing ES6 promises in node.js to send a null response

I'm looking for assistance on how to execute a query using ES6 native promises in node.js. The code I have below is what I've been working with: let arr= []; conn.query('select * from table1', (err, b) => { for (let i = 0; i ...

Monitoring the actions that occur when my button is clicked using Firefox and Javascript

Whenever I click on a few new buttons that I've recently added, something weird is happening. The buttons are functioning correctly, but they keep scrolling the page back to the top. I suspect that there might be some interference from another part of ...

What is the best way to input data into the verified full name box?

.html file executed code <input type="name" [(model)]="x.name" class="form-control" pattern="[a-z]" > Greetings to the members of Stack, I am in need of assistance. I am relatively new to Angular and I am looking for a way to validate the full nam ...

How can I pass arguments from a Python command line program (compiled to an EXE) to a JavaScript file?

As I work on developing a node program, I've come across certain abilities that Python possesses which JavaScript lacks, such as utilizing Python-specific modules. To bridge this gap, I made the decision to compile Python files into EXE and then invok ...

Using ExpressJS and Jade to submit a form using the POST method and redirecting to a specified path

I am exploring node, express and jade for the first time and working on a small application that requires users to enter their name and password in a form. The app then redirects them to a path based on their username. Here is the code snippet to achieve ...