Retrieve server information without utilizing data.map since array.map is not a supported function in next.js version 13

Currently, I am developing a list page using next.js 13 to display a collection of projects.

I made an attempt to enable server-side rendering for this feature.

The implementation is located in app/team/page.tsx

import { useRouter } from 'next/navigation';
export default async function useProjects() {
  const res = await fetch('/api/projects')
  if (!res.ok) {
    throw new Error('Failed to fetch data')
  }
  return res.json()
}

import useProjects from '@/hooks/use-projects';    
import { useRouter} from 'next/navigation';

const Team = () => {

  const  projects  = useProjects();
  console.log('projects ', projects);

  return (
    <SettingsLayout
      title="Projects"
      RightHeading={
        <>

        </>
      }
    >
      <div className="grid grid-cols-1 gap-4 sm:grid-cols-3">
        {
          projects.map((project) => (
            <Link
              key={`project-card-${project.slug}`}
              href={`/${team?.slug}/${project.slug}`}
            >
              <div className="truncate whitespace-nowrap rounded-lg border border-neutral-800 bg-neutral-1000 p-8 text-neutral-100 transition hover:bg-neutral-900">
                {project.name}
              </div>
            </Link>
          ))}
      </div>
    </SettingsLayout>
  );
};

export default Team;

The server successfully retrieves the project data and displays it in the console log.

https://i.stack.imgur.com/KfZOs.png

However, the page layout does not render correctly.

https://i.stack.imgur.com/lF02K.png

Update

Following @Phil's approach, I implemented client-side rendering.

import { useEffect, useState } from "react";
const fetchProjects = async () => {
   // Mocked data
  const data = [{"id":"f0dc4b06-063a-4ed7-a712-463b418ae436","slug":"starter","name":"Starter","is_starter":true}];
  return data;
};


export default async function useProjects() {
  const [projects, setProjects] = useState<[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<Error>();

  // Fetch projects on mount
  useEffect(() => {
    setLoading(true);
    try{
      let data =  fetchProjects();
      console.log('get data ',data);  // outputs the fetched data

/*
get data   
Promise {<pending>}
[[Prototype]]: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: Array(1)
*/
      setProjects(data);
    }catch(error){
      setError(error)
    } 
    setLoading(false);

  }, []);
  return { projects, loading, error };
} 

However, in another components

const Team = () => {

  const { projects, loading, error } =  useProjects();
  console.log('projects', projects);

  .... 

}

The error has been resolved, but the console output shows 'undefined' for projects. The component does not have access to the projects data.

If I avoid using the hook and embed the code directly into the component:

  const [projects, setProjects] = useState<[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<Error>();
  useEffect(() => {
    const fetchProjects = async () => {
      const res = await fetch("/api/projects");
      const data = [{"id":"f0dc4b06-063a-4ed7-a712-463b418ae436","slug":"starter","name":"Starter","is_starter":true}];
      setProjects(data);
    };
    fetchProjects();
  }, []);

In this case, the functionality works as expected.

I am curious as to why the hook failed to retrieve the necessary data.

Answer №1

useProjects does not return an array, but rather a promise.

To handle asynchronous state management, it is advisable for your custom hook to internally maintain and update the state when the fetch() request is resolved.

Additionally, keeping track of both the loading and error states is essential.

// Hypothetical `Project` type assumed

const fetchProjects = async (): Promise<Project[]> => {
  const res = await fetch("/api/projects");
  if (!res.ok) {
    throw new Error('Failed to fetch data');
  }
  return res.json();
};

export default async function useProjects() {
  const [projects, setProjects] = useState<Project[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<Error>();

  // Fetch projects on component mount
  useEffect(() => {
    setLoading(true);
    fetchProjects()
      .then(setProjects)
      .catch(setError)
      .finally(() => {
        setLoading(false);
      });
  }, []);

  // Return the state
  return { projects, loading, error };
}

Subsequently, utilize the hook within your components:

const { projects, loading, error } = useProjects();

The error and loading states can be utilized for determining rendering logic.


Frameworks like Tanstack Query excel in handling such operations efficiently. It's worth exploring these options.

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

Utilizing Typescript to pass props to a material-ui button enclosed in styled-components

After setting up my react project using the typescript template, I decided to style the material-ui Button component using the 'styled' method from the styled-components library as shown below: import React from 'react'; import styled f ...

What is the equivalent of defining conditional string types in Typescript similar to flow?

type UpsertMode = | 'add' | 'update' | 'delete'; interface IUpsertMembers { mode: UpsertMode; } const MagicButton = ({ mode: UpsertMode }) => { return ( <button>{UpsertMode}</button> ); } const Upse ...

NPM: There are no valid TypeScript file rules specified

Currently working on a small project using React.JS. Whenever I execute : npm run start, the following message gets logged: Starting type checking and linting service... Using 1 worker with 2048MB memory limit Watching: /Users/John/Projects/myProject/src ...

The error message states that the property "user" is not found in the type "Session & Partial<SessionData>"

I recently had a javascript code that I'm now attempting to convert into typescript route.get('/order', async(req,res) => { var sessionData = req.session; if(typeof sessionData.user === 'undefined') { ...

Encountering an Internal Server Error while running NextJs 13 in production environment, integrated with sanity and net

About I'm currently using Next.js and hosting my website on Netlify with CMS being Sanity. The blog page, which fetches content from Sanity, is encountering a 500 Internal Server Error when deployed on Netlify. However, it functions properly during l ...

There seems to be an issue with the product being undefined in the fake store API when using the console in Next Js within

When working with the fake store API in Next.js, I encountered an issue where the product was showing as undefined in the console. Even after trying to debug using various methods, such as console.log(product), the issue persisted and the product remained ...

Utilizing Typescript to Incorporate Bable's Latest Feature: The 'Pipeline Operator'

Exploring the pipeline operator implementation in my Typescript project has been quite a journey. Leveraging babel as my trusty transpiler and Typescript as the vigilant type checker was the initial plan. The quest began with configuring babel to work sea ...

The occurrence of a loading error arises when attempting to load the second component, displaying the message 'The template instructed for component SidebarComponent is

My journey with Angular has just begun, and I decided to challenge myself by creating a simplistic dashboard. In order to achieve this, I developed two components called DashboardComponent and SidebarComponent. The DashboardComponent loads smoothly witho ...

What causes TypeScript to malfunction when using spread in components?

What is the reason for typescript breaking when props are sent to a component using a spread statement? Here's an example code snippet: type SomeComponentProps = Readonly<{ someTitle: string }> const SomeComponent = ({ someTitle }: SomeCompo ...

What is the best way to test chained function calls using sinon?

Here is the code I am currently testing: obj.getTimeSent().getTime(); In this snippet, obj.getTimeSent() returns a Date object, followed by calling the getTime() method on that Date. My attempt to stub this functionality looked like this: const timeStu ...

Unable to attach to 'leafletOptions' as it is unrecognized as a property of 'div'

It seems like I keep encountering this problem, which is often resolved by adjusting import statements. Right now, my imports look like this: import { LeafletModule } from 'node_modules/@asymmetrik/ngx-leaflet'; import * as L from 'leaflet& ...

Misunderstanding between Typescript and ElasticSearch Node Client

Working with: NodeJS v16.16.0 "@elastic/elasticsearch": "8.7.0", I am tasked with creating a function that can handle various bulk operations in NodeJS using Elasticsearch. The main objective is to ensure that the input for this funct ...

What types should be used when passing a NgRx Action as a parameter to a function?

Within my Effects function, I have implemented the following code structure. I have included a few lines of code for the catchError block to ensure that: Any errors are handled by the state/store The errors are forwarded to the global error handler / Int ...

When no values are passed to props in Vue.js, set them to empty

So I have a discount interface set up like this: export interface Discount { id: number name: string type: string } In my Vue.js app, I am using it on my prop in the following way: export default class DiscountsEdit extends Vue { @Prop({ d ...

Typescript: The original type cannot be indexed with a type-mapped type

I'm currently working on a class where I need to define a method that returns an object with keys based on the generic type inferred by the compiler. However, I've encountered an issue with the code snippet below. The compiler is indicating that ...

Optimizing Firebase and Next.js for serverless deployment on Google Cloud Platform: A guide to effectively managing staging, production, and

Currently, I am utilizing React along with next.js and Google Cloud functions to host my application. Additionally, I am integrating firebase into the mix. One pressing issue I am facing pertains to efficiently configuring the staging and production enviro ...

Auth.js and Next.js, route error with callback handling

When deploying the app on a server using auth.js with credentials provider, an error is encountered. Interestingly, there are no errors when running the app on localhost. The login page structure can be seen below: 'use client' import { Label } ...

Nginx Experiencing Persistent Failures Due to 'Signal' Issue

Currently, we have a DigitalOcean machine running on 5.15.0-100-generic #110-Ubuntu, hosting multiple NextJS frontends and a NodeJS backend through PM2 on various localhost ports. These projects are accessible via different subdomains of the main domain wi ...

Distribute your SolidJS Typescript components on npm

Recently, I developed a SolidJS TypeScript UI component and successfully published it to the npm registry. The project structure is organized as follows: |-app |-index.html |-src |-index.tsx |-App.tsx |-utils |- ... |-com ...

Developing a React-based UI library that combines both client-side and server-side components: A step-by-step

I'm working on developing a library that will export both server components and client components. The goal is to have it compatible with the Next.js app router, but I've run into a problem. It seems like when I build the library, the client comp ...