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