TS2786: 'Component' cannot be used as a JSX component
問題の概要
React TypeScriptアプリケーションで、コンポーネントのコンパイル時に以下のエラーが発生することがあります:
TS2786: 'MessagesWidget' cannot be used as a JSX component.
Its instance type 'MessagesWidget' is not a valid JSX element.
The types returned by 'render()' are incompatible with these types.
Type 'React.ReactNode' is not assignable to type 'import("/home/node/app/node_modules/@types/react-calendar/node_modules/@types/react/index").ReactNode'.
このエラーは、React.ReactNode
や React.ReactElement
を返すように型付けられているコンポーネントのレンダーメソッドで発生し、react-calendar
などのサードパーティライブラリがバンドルしている型定義との互換性問題が原因です。
根本原因
主な原因は、プロジェクト内での @types/react
のバージョンの不一致です。React 18の型定義では、いくつかの破壊的変更が導入され、異なるバージョンの @types/react
を使用するライブラリ間で互換性の問題が発生します。
WARNING
この問題はコード変更なしで突然発生することが多く、パッケージの自動更新(特に @types/react
と @types/react-dom
)が引き金になることがよくあります。
解決策
1. 型定義のバージョン統一(推奨)
パッケージマネージャーの解決策機能を使用して、すべての依存関係が同じバージョンの @types/react
を使用するように強制します。
Yarnを使用の場合(package.json):
{
"resolutions": {
"@types/react": "18.0.26",
"@types/react-dom": "18.0.26"
}
}
npmを使用の場合(package.json):
{
"overrides": {
"@types/react": "18.0.26",
"@types/react-dom": "18.0.26"
}
}
適用後、以下のコマンドでクリーンインストールを実行します:
rm -rf node_modules package-lock.json yarn.lock
npm install
# または
yarn install
2. TypeScript設定の調整
tsconfig.json に以下の設定を追加します:
{
"compilerOptions": {
"paths": {
"react": ["./node_modules/@types/react"]
}
}
}
この設定により、TypeScriptが常にプロジェクトルートの @types/react
を使用するようになります。
3. 非互換ライブラリの特定と対応
以下のコマンドで、どのパッケージが異なるバージョンの @types/react
に依存しているかを調査します:
npm explain @types/react
# または
yarn why @types/react
TIP
styled-components
v6を使用している場合、これは独自の型定義を含んでいるため、@types/styled-components
をアンインストールする必要があるかもしれません。
4. コンポーネントレンダリングの問題修正
コンポーネントが正しくJSX要素を返していることを確認します。以下のような一般的なパターンに注意してください:
問題のあるコード:
// React Nodeではないものを返している
if (!isLoggedIn) return router.push("/login");
// 非同期コンポーネント(React 18ではサポートされていない)
export async const Component = () => {
// ...
}
// childrenを直接返している
export const Component = ({ children }) => {
return children;
}
修正後のコード:
// リダイレクト処理
if (!isLoggedIn) {
router.push("/login");
return <></>;
}
// 同期コンポーネント
export const Component = () => {
const asyncFunction = async () => {
// 非同期処理
};
// ...
}
// childrenをフラグメントでラップ
export const Component = ({ children }) => {
return <>{children}</>;
}
その他の解決策
TypeScriptと型定義の更新
最新バージョンのTypeScriptと型定義パッケージを使用することで問題が解決することがあります:
npm install --save-dev typescript@latest @types/react@latest @types/react-dom@latest
React Nativeプロジェクトの場合
React Nativeプロジェクトでは、tsconfig.json に以下の設定を追加します:
{
"compilerOptions": {
"types": ["react-native", "jest"]
}
}
キャッシュのクリア
ロックファイルとnode_modulesを削除して再インストールします:
rm -rf node_modules yarn.lock
yarn install
まとめ
TS2786エラーは主に @types/react
のバージョン不一致が原因です。以下の方法で解決できます:
- resolutions/overrides を使用した型定義のバージョン統一
- tsconfig.json の適切な設定
- コンポーネントのレンダリングロジックの確認
- 非互換ライブラリの特定と対応
プロジェクトの規模や使用しているライブラリに応じて、適切な解決策を選択してください。大規模なプロジェクトでは、型定義のバージョンを統一することが最も確実な解決法となります。