💡
[Next.js]サーバーコンポーネントを呼び出すとJSX コンポーネントとして使用することはできません。と表示される
環境
"next": "latest",
"prettier": "^3.3.3",
"react": "19.0.0",
"react-dom": "19.0.0",
"@types/react": "^17.0.39",
エラー内容
開発中に例えば、Aboutページでサーバーコンポーネントを呼び出します
Aboutページ
import { LowerTitle } from "../components/ui/"
import { LicenseList } from "../components/ui/rsc"
export const metadata: Metadata = {
title: "To You Design - About",
description: "Generated by Next.js",
}
const About = () => {
return (
<main className="u-padding">
<LicenseList />
</main>
)
}
export default About
資格表示サーバーコンポーネント
import { fetchLicenses } from "hooks/fetch"
/**
* 資格のタイムライン
*/
export const LicenseList = async () => {
const data = await fetchLicenses()
return (
<>
{data?.data.map((license) => (
<tr key={license.id} className="license__table-tr">
<td className="license__table-td">{license.date}</td>
<td className="license__table-td">{license.title}</td>
</tr>
))}
</>
)
}
ですが、この状態だとエラーが出ない想定でしたが、下記のエラーが出ました。
'LicenseList' を JSX コンポーネントとして使用することはできません。
その戻り値の型 'Promise<Element>' は、有効な JSX 要素ではありません。
型 'Promise<Element>' には 型 'ReactElement<any, any>' からの次のプロパティがありません: type, props, key
たしかに、LicenseListは、asyncがついてる為、戻り値が () => Promise<JSX.Element> こうなっています。
上記ですが、上手く対処できず、実装自体もおかしくないため、そのままになっていました。
上記の記事だと、
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. We are working with the TypeScript team to resolve this upstream. As a temporary workaround, you can use {/* @ts-expect-error Server Component */} to disable type checking for the component.
と記載がありました。
そのため、暫定対処として、下記の対応をしていました。
{/* @ts-expect-error 非同期サーバーコンポーネントはPromiseを返すため型エラーになりますが、Next.jsが実行時に解決します */}
<LicenseList />
対処法
対処法として、シンプルで、上記の記事を参考にし、@types/reactをv18にアップします。
"@types/react": "^18.0.0",
エディタを再起動するとエラーの表示がなくなり、問題の解決しました。
2年前くらいに作ったプロジェクトのため、Next.js, Reactのアップデートなどはしていましたが、@types/reactのバージョンアップを忘れていました・・・。
古いプロジェクトで上記のエラーが出る場合はぜひ試してみてください。
Discussion