6

I was playing with the experimental Next 13 app directory.

As per the documents, a client component can accept a server component, as long as it is as a children prop.

It works, however I do get a type error

'ServerPage' cannot be used as a JSX component. Its return type 'Promise' is not a valid JSX element. Type 'Promise' is missing the following properties from type 'ReactElement<any, any>': type, props, key

import ClientPage from './clientPage';
import ServerPage from './serverPage';

// app/page.tsx
export default function Home() {
  // logs in the server
  console.log('rendering home page');

  return (
    <>
      <ClientPage>
        <ServerPage /> // type error here
      </ClientPage>
    </>
  );
}

the serverPage.tsx component

const fetchSomeData = async () => {
  const response = await fetch('https://pokeapi.co/api/v2/pokemon/ditto');

  if (!response.ok) {
    throw new Error(response.statusText);
  }

  return response.json();
};

export default async function ServerPage() {
  const data = await fetchSomeData();
  // this logs in the server
  console.log(data);

  return (
    <>
      <main className={styles.main}>
        Im a server component
      </main>
    </>
  );
}

the clientPage.tsx component

'use client';

export default function ClientPage({
  children,
}: {
  children: React.ReactNode;
}) {
  // this logs in the client
  console.log('rendering client page');
  return (
    <>
      {children}
    </>
  );
}

I suppose that this has to do with the children type in the clientPage component, but I'm not sure how this should be typed.

Yilmaz
  • 35,338
  • 10
  • 157
  • 202
Fer Toasted
  • 1,274
  • 1
  • 11
  • 27

3 Answers3

2

Async Server Component TypeScript Error

To use an async Server Component with TypeScript, ensure you are using TypeScript 5.1.3 or higher and @types/react 18.2.8 or higher.

If you are using an older version of TypeScript, you may see a 'Promise' is not a valid JSX element type error. Updating to the latest version of TypeScript and @types/react should resolve this issue.

next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: { serverActions: true },
};

module.exports = nextConfig;

``
Chukwuemeka Maduekwe
  • 6,687
  • 5
  • 44
  • 67
1

Unfortunately, the only way around this at the moment is to use the :any type definition on the async server components. Next.js 13 outlined this in their Typescript documentation.

Warning: You can use async/await in layouts and pages, which are Server Components. Using async/await inside other components, with TypeScript, can cause errors from the response type from JSX. You might see the error 'Promise' is not a valid JSX element. We are tracking this issue here.

Wesley LeMahieu
  • 2,296
  • 1
  • 12
  • 8
0

This is a bug. Next.js team has been working on it. You could also use eslint comment

  <ClientPage>
    // @ts-expect-error Server Component
    <ServerPage /> // type error here
  </ClientPage>
Yilmaz
  • 35,338
  • 10
  • 157
  • 202