Issue with Next.js 14: Server Component causing app crashes when tabs with ShadowCN are repeatedly fetched and changed

I'm currently developing a Next.js 14 application that utilizes ShadCN for UI components and TanStack Query for data fetching. The main screen of the app features a Tabs component that enables users to switch between different sections. One of these sections includes an async server component responsible for making a fetch request to retrieve and display a list of elements.

The Issue:

Upon initial loading of the app, the server component is set as the default tab. However, when I switch to another tab and then return to the server component tab, it starts to continuously make fetch requests in a loop, eventually leading to a crash of the application. Following the crash, the error message "Error: async/await is not yet supported in Client Components, only Server Components..." is displayed.

I attempted to manage the rendering of tabs based on the state of the Tabs selection rather than letting the Tabs component handle it naturally. This approach allowed me to navigate to the second tab successfully, but upon returning to the original main tab, the same looping issue occurred.

Code for the server component and a commented-out definition of the fetching function

import { getCandidates } from "@api";
import { TabsContent } from "@components";

// const url = process.env.NEXT_PUBLIC_API_URL;

// export const getCandidates = async (): Promise<Candidate[]> => {
//   const response = await fetch(`${url}/v1/candidates`, { method: "GET" });

//   return response.json();
// };

export default async function CandidatesContent() {
  // const cand = await fetch(`${url}/v1/candidates`, { method: "GET" });
  const candidates = await getCandidates();
  console.log(candidates);
  return (
    <TabsContent value="candidates">
      <div>
        {candidates.map((candidate) => (
          <p key={candidate.id}>{candidate.name}</p>
        ))}
      </div>
    </TabsContent>
  );
}

Main page containing the Tabs

"use client";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components";
import CandidatesContent from "@/components/candidatesContent/CandidatesContent";
import { useState } from "react";

export default function Home() {
  const [activeTab, setActiveTab] = useState("candidates");

  return (
    <main className="container mx-auto py-4 px-6">
      <Tabs value={activeTab} onValueChange={setActiveTab} className="">
        <div className="flex justify-center">
          <TabsList>
            <TabsTrigger value="candidates">Candidates</TabsTrigger>
            <TabsTrigger value="results">Results</TabsTrigger>
          </TabsList>
        </div>
        <CandidatesContent />
        <TabsContent value="results">
          <div>results</div>
        </TabsContent>
        {/* {activeTab === "candidates" && <CandidatesContent />} */}
        {/* {activeTab === "results" && (
          <TabsContent value="results">
            <div>results</div>
          </TabsContent>
        )} */}
      </Tabs>
    </main>
  );
}

Query: How can I prevent the server component from continuously re-rendering as it currently does? And what is causing this behavior?

Answer №1

The process of importing a server component into a client component is not recommended. It is advisable to either convert the Home() function into a server component or transform the server component into a client component.

Answer №2

Encountering the same problem here too: https://github.com/shadcn-ui/ui/issues/2741 To resolve this issue, you can utilize the forceMount={true} function and hide the content when the tab is not selected. See example below:

 <TabsContent
          forceMount={true}
          value="withdraw"
          hidden={"results" !== activeTab}
        >
           <div>results</div>
 </TabsContent>

Explanation: forceMount={true} is a feature in Shadcn UI's Tabs component that ensures all TabsContent components are rendered upon component mounting, rather than only upon activation.

By default, TabsContent components are rendered only when their corresponding TabsTrigger is activated. This means that if you switch to another tab, the inactive TabsContent will be unmounted, potentially leading to loss of filled form data or state.

Using forceMount={true} guarantees that all TabsContent components are fully rendered and mounted in the DOM upon initial load, regardless of activation status. This prevents data loss from content re-rendering.

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

Achieve flattening of types using recursion in TypeScript with the help of const

I am presenting the TypeScript code below: type Item = { key: number; value: string; items?: readonly Item[]; } const items = [ { key: 1, value: 'foo', items: [{ key: 3, value: 'baz' }] }, { key: 2, value: 'bar ...

Using a memory cache in development with NextJS does not seem to be effective

When exporting my pages for my simple static blog site, everything runs smoothly and quickly. However, in development mode, the generation of posts is sluggish and I'm looking to implement caching to speed up the process. I have set up a file called p ...

return to the original secured page based on the most recent language preference

I'm facing an issue with a logical redirection that needs to redirect users to the previous protected page after login. The login functionality is implemented using my custom login page and Google Credentials. Additionally, I have set up a multilingu ...

Prisma is continuously spitting out data beyond my jurisdiction

I'm currently working on a project that involves postgreSQL and Prisma. While debugging in getServerSideProps(), I noticed that Prisma is automatically console.logging long strings like the following: prisma:query SELECT "public"."TaskC ...

utilizing a reusable design in the nextjs directory for pages

If I have the following files in my /pages directory and want to utilize the same template for cats/[slug] and dogs/[slug] routes (excluding fish), what steps should I take? Currently, I am duplicating the file... index.js cats.js dogs.js fish.j ...

Tips for creating a custom script in my React Native application

My React Native app requires a script to generate static files during the release process. The app is a game that utilizes pre-computed boards, which are resource-intensive to compute. Therefore, I am developing a script that will create these boards and s ...

Issues arise when Angular properties become undefined following the initialization or OnInit functions

There seems to be a peculiar issue with the properties of an angular component that I have set up. It appears that these properties are losing their values after the initialization process. The component is essentially a basic HTML file containing a video ...

Nested arrays in an Angular interface

As a newcomer to Angular with a background in Java, I am accustomed to setting up classes as data structures for my information. However, after doing some research, I have learned that interfaces should be used instead. I am facing an issue understanding ...

What is preventing the dependency injection of AuthHttp (angular2-jwt) into a component?

UPDATE: Success! Problem Solved After much trial and error, I finally discovered the solution to my issue. It turned out that the problem lied in a simple configuration mistake. To rectify this, I made changes to both my package.json (dependencies section ...

Following mouse element delay issue in the latest directory of a Next.js 13 application

I'm working on a project where I want to create an element that follows the mouse as it moves across the screen. I decided to use framer motion for the animation and found a helpful example in their documentation: Check out this example from framer mo ...

a guide to transforming data into a string with json using angular

I am struggling to figure out how to bind my form data into a JSON string. My situation involves using a string field in the database and saving checkbox values in a single database column using JSON. I have created an HTML form, but I am unsure of how to ...

Adjusting the audio length in React/Typescript: A simple guide

I'm currently developing a web app with React and TypeScript. One of the components I created is called SoundEffect, which plays an mp3 file based on the type of sound passed as a prop. interface ISoundEffectProps { soundType: string, // durat ...

Is it possible to apply filters to individual columns in a dynamic mat table using Angular?

Does anyone know how to add a filter for each dynamic column in an Angular Material table? I've only found solutions for static headers, but my table headers are constantly changing. I'm looking for something similar to this example: https://i.st ...

Combine Immer and NgRx reducer for improved state management

Upon analyzing redux and ngrx, it appears that immer is the preferred library for creating a copy of the state before storing it. In following the example provided by immer, I implemented the following code in my reducer: on(exampleActions.updateExample ...

Sorting the material table based on the column IDs, which usually correspond to the column names, may not align with the properties of the data

.ts this.displayedColumns = [ { key: 'id', header: '#' }, { key: 'fullname', header: 'Full name' }, { key: 'email', header: 'email' }, { key: 'roleName', header: ...

Supplier for a module relying on data received from the server

My current component relies on "MAT_DATE_FORMATS", but I am encountering an issue where the "useValue" needs to be retrieved from the server. Is there a way to make the provider asynchronous in this case? export const MY_FORMATS = { parse: { d ...

Implementing canActivate guard across all routes: A step-by-step guide

I currently have an Angular2 active guard in place to handle redirection to the login page if the user is not logged in: import { Injectable } from "@angular/core"; import { CanActivate , ActivatedRouteSnapshot, RouterStateSnapshot, Router} from ...

What is the reason behind capitalizing Angular CLI class file imports?

After creating a basic class in Angular using the CLI starter, I encountered an issue when trying to use the imported class. Instead of functioning as expected, it returned an empty object. Through troubleshooting, I discovered that simply changing the fil ...

Issue TS2349 occurs when attempting to use a combination of boolean and function types within union typing

In my class, there is a property called "isVisible" which can be either a boolean value or a function that returns a boolean. The code snippet below demonstrates what I am currently using. It works fine and achieves the desired result, but during compilat ...

The interface 'HTMLIonIconElement' is not able to extend both 'IonIcon' and 'HTMLStencilElement' types at the same time

After upgrading my Angular Ionic app to use Angular v13 from Angular 12 with the command ng update, I encountered errors preventing me from running the application successfully. [ng] Error: node_modules/ionicons/dist/types/components.d.ts:66:15 - error TS2 ...