What is the best way to design a basic server component that has the ability to retrieve data in NextJS 13?

Exploring the world of NextJS, I am currently utilizing NextJS 13 with the new app directory instead of the traditional pages directory structure. Despite trying various methods to fetch data, none seem to be working as expected. The process should be straightforward:

In src/app/page.tsx:

export interface ToDo {
  userId: number;
  id: number;
  title: string;
  completed: boolean;
}

const getToDos = async (): Promise<ToDo[]> => {
  const res = await fetch('https://jsonplaceholder.typicode.com/todos/1');
  console.log(`Status: ${res.status}`); // prints 'Status: 200'
  return res.json();
}

const Home = async () => {
  const toDos = await getToDos();
  return (
    <ul>
      {toDos.map((todo) => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  );
}

export default Home;

The JSON response from the endpoint is:

{
  "userId": 1,
  "id": 1,
  "title": "delectus aut autem",
  "completed": false
}

Upon execution, both a successful 200 status and an error message are displayed:

Warning: Only plain objects can be passed to Client Components from Server Components. Classes or other objects with methods are not supported.
  <... client={{queryCache: ..., mutationCache: ..., logger: ..., defaultOptions: ..., queryDefaults: ..., mutationDefaults: ..., mountCount: ...}} children=...>
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Warning: Only plain objects can be passed to Client Components from Server Components. Classes or other objects with methods are not supported.
  {queryCache: {listeners: Set, subscribe: function, config: ..., queries: ..., queriesMap: ...}, mutationCache: ..., logger: ..., defaultOptions: ..., queryDefaults: ..., mutationDefaults: ..., mountCount: ...}
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Status: 200

-  ┌ GET / 200 in 606ms
   │
   └──── GET https://jsonplaceholder.typicode.com/todos/1 200 in 67ms (cache: HIT)

- error node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js (1863:12) @ resolveModelToJSON
- error Error: Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server".
  {listeners: Set, subscribe: function, config: ..., queries: ..., queriesMap: ...}
                              ^^^^^^^^
    at stringify (<anonymous>)
null
- error node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js (1863:12) @ resolveModelToJSON
- error Error: Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server".
  {listeners: Set, subscribe: function, config: ..., queries: ..., queriesMap: ...}
                              ^^^^^^^^
    at stringify (<anonymous>)
digest: "501055159"
null

Introducing "use server" at the start of page.tsx triggers compilation errors:

Server Actions require `experimental.serverActions` option to be enabled in your Next.js config: https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions

While my goal is to generate HTML statically, for now, I would greatly appreciate functional data fetching scripts.

Update

Having previously experimented with Tanstack Query, I have since removed all related code from my layout.tsx file. However, I now encounter a different issue with the following code:

export default async function Home(): Promise<JSX.Element> {
  const todos = await getToDos();
  console.log(todos);
  return (
    <ul>
      {todos.map((todo) => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  );
}

resulting in the error:

error TypeError: todos.map is not a function

Answer №1

It appears that you are attempting to transfer a function from a server component to a client component, which is not allowed unless it is a server action. Currently in alpha stage, server actions need to be enabled by configuring experimental.serverActions in your next.config.js file:

module.exports = {
  experimental: {
    serverActions: true,
  },
};

Below is an example of a server-side component:

import "server-only";

interface ToDo {
  userId: number;
  id: number;
  title: string;
  completed: boolean;
}

async function getToDos(): Promise<ToDo[]> {
  const res = await fetch("https://jsonplaceholder.typicode.com/todos");
  return await res.json(); // You missed an 'await' here
}

export default async function Home(): Promise<JSX.Element> {
  const todos = await getToDos();
  return (
    <ul>
      {todos.map((todo) => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  );
}

I highly recommend installing the server-only package to prevent errors when trying to import a server component into the client side.

Answer №2

As @FabioNettis astutely observed, I was attempting to retrieve a lone object that was not iterable. By mistakenly trying to fetch from the incorrect path /todos/1 instead of /todos, my fetching code appeared to be accurate, albeit subpar. Implementing proper error handling would have facilitated the debugging process.

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

Solving the issue of font awesome override in nextJS

Currently, I am integrating FontAwesome into my NextJS project with Tailwind CSS. Following the official documentation, it instructs to add the given code snippet to _app.tsx file: import { config } from "@fortawesome/fontawesome-svg-core"; impor ...

How can I add an image to my Material-UI Next.js project?

After importing the image in this way: import img from '../public/buildingspattern.png' I then utilized it within the component like so: <Card className={classes.root}> <CardMedia className={classes.media} imag ...

Angular2 and Typescript paired with Visual Studio 2013

Currently, I am utilizing the angular2 QUICKSTART and encountering an issue where Visual Studio fails to recognize Angular2 with typescript import Modules. However, everything else seems to be functioning correctly: https://i.stack.imgur.com/0s46Y.jpg Th ...

Challenges encountered when unit testing ngx-translate

0 I am encountering issues with unit testing while using the ngx-translate library. Despite adding a provider for TranslateService, the tests keep asking for more providers, creating an endless loop of dependencies. Specifically, I am trying to unit test ...

Receiving an error in TypeScript stating that the property or data does not exist on the type for Vue props

I've recently integrated TypeScript into my Vue project, and now I'm encountering an error every time I try to access a value in props or data: 37:46 Property 'activity' does not exist on type '{ props: { activity: { type: ObjectC ...

eliminating parameters in URL for redirection in Next.js

I'm encountering an issue with the code snippet provided. When I try to redirect to /home and pass an email variable, the address bar displays http://localhost:4000/[email protected]. Can anyone suggest a clean way to pass variables using react a ...

How come the icon doesn't update on the client side after being rendered on the server side?

Currently implementing a Daisyui theme switcher in my nextjs project. It's mostly working fine, but there are some issues I'm having trouble with. I've created a simple theme switch button: // Themeswitch.jsx 'use client'; impor ...

What methods can TypeScript employ to comprehend this situation?

There's an interesting scenario when it comes to assigning a variable of type unknown to another variable. TypeScript requires us to perform type checking on the unknown variable, but how does TypeScript handle this specific situation? It appears that ...

The JSX Configuration in TypeScript: Comparing ReactJSX and React

When working with Typescript and React, it's necessary to specify the jsx option in the compilerOptions section of the tsconfig.json file. Available values for this option include preserve, react, react-native, and react-jsx. { "compilerOptions": { ...

Can you please explain how I can retrieve information from a Firebase collection using the NextJs API, Firebase Firestore, axios, and TypeScript?

I'm currently utilizing api routes within NextJS 13 to retrieve data from Firebase. The code for this can be found in api/locations.tsx: import { db } from "../../firebase"; import { collection, getDocs } from "firebase/firestore"; ...

Having trouble getting a local npm installation to work from a specific file path?

After following the instructions from this helpful link to install an npm package through a file path, I encountered an error when attempting to use it: Cannot find module '<module_name>' or its corresponding type declaration Are there an ...

How can TypeScript be used to enable CSV or PDF export in a material-react-table?

Is it possible to incorporate the ability to export data to CSV or PDF in a material-react-table? While I am familiar with how to do this with a Material UI table, I have not been able to find the same functionality for the material-react-table. Thank you ...

Leverage tsconfig.json within the subfolders located in the app directory during Angular build or ng-build process

In our Angular project, I am attempting to implement multiple tsconfig.json files to enable strictNullChecks in specific folders until all errors are resolved and we can turn it on globally. I have been able to achieve this functionality by using "referen ...

Looking to categorize and sum the values within an array of objects using JavaScript?

I'm looking to optimize this response data within my Angular application. res=[ { "url": "/page1", "views": 2 }, { "url": "/page2", "views": 1 }, { "url": "/page1", "views": 10 }, { "url": "/page2", "views": 4 }, { "url": "/page3", "views": 1 }, ...

Issues with identifying the signature of a class decorator arise when invoked as an expression

I've been following this coding example but I'm running into issues when trying to compile it. Any suggestions on how to troubleshoot this error? import { Component } from '@angular/core'; function log(className) { console.log(class ...

Creating a custom event handler for form input changes using React hooks

A unique React hook was created specifically for managing form elements. This hook provides access to the current state of form fields and a factory for generating change handlers. While it works seamlessly with text inputs, there is a need to modify the c ...

The type "Props" is considered invalid in Next.js version 13

When attempting to execute yarn build for my next project, I encountered an error during the build process. Type error: The layout "app/dashboard/tpp/components/layout.tsx" has an invalid "default" export: Type "Props" is not valid. Does anyone have any i ...

Presentation of information with loading and error scenarios

How can we effectively display data in an Angular view, considering loading state and error handling? Imagine we are fetching a set of documents from our backend and need to present them in an Angular view. We want to address three possible scenarios by p ...

You are unable to call upon an object that may be of type 'undefined' in typescript

Among all the other inquiries on this topic, my issue lies with the typescript compiler seeming perplexed due to the following code snippet: if(typeof this[method] === "function"){ await this[method](req,res,next) } The error message I am en ...

What is the best way to access an API located in a different pod within the same Kubernetes development cluster and namespace from a NextJS pod?

Incorporating a NextJS app into our namespace's dev cluster has been a smooth process. When running Kubectl get all --namespace [my-namespace], the following information is returned: NAME READY STATUS RESTAR ...