Type error: JSX element type '{} | null | undefined' is not a constructor function for JSX elements
Type error: JSX element type '{} | null | undefined' is not a constructor function for JSX elements
我有一个名为 HandleQuery
的 React 组件,用于处理 Apollo GraphQL 查询的结果:
import React, { ReactNode } from 'react';
import { CenteredMessage } from './centered-message';
export interface HandleQueryProps {
loading: boolean,
error?: Error,
children: ReactNode
}
export const HandleQuery = ({ loading, error, children }: HandleQueryProps) => {
if (loading) {
return <CenteredMessage>Loading...</CenteredMessage>;
}
if (error) {
return <CenteredMessage>{error.message}</CenteredMessage>;
}
return children;
};
当此组件用于另一个组件时,它不会编译:
import React from 'react';
import { useQuery } from 'react-apollo-hooks';
import gql from 'graphql-tag';
import { HandleQuery } from '..';
import { MutationType } from '../../graphql-types';
import { AuthorsPanel } from './authors-panel';
import { GET_AUTHORS } from './authors-queries';
import { AuthorMutated } from './__generated__/AuthorMutated';
export class AuthorsContainer extends React.Component {
render() {
const { loading, error, data } = useQuery(GET_AUTHORS);
return (
<!-- THIS LINE PRODUCES A COMPILER ERROR -->
<HandleQuery loading={loading} error={error}>
<AuthorsPanel data={data} />
</HandleQuery>
);
}
}
使用上面的 HandleQuery
会产生以下错误:
Type error: JSX element type '{} | null | undefined' is not a constructor function for JSX elements.
Type 'undefined' is not assignable to type 'Element | null'. TS2605
这是什么意思,我该如何摆脱它?
更新
将 AuthorsContainer 转换为函数组件并不能消除错误:
export const AuthorsContainer = () => {
const { loading, error, data } = useQuery(GET_AUTHORS);
return (
<HandleQuery loading={loading} error={error}>
<AuthorsPanel data={data} />
</HandleQuery>
);
};
更新 2
来自@FredyC 的实施建议:
import React from 'react';
import { CenteredMessage } from './centered-message';
export interface HandleQueryProps {
loading: boolean;
error?: Error;
}
export const HandleQuery: React.FC<HandleQueryProps> = ({
loading,
error,
children
}) => {
if (loading) {
return <CenteredMessage>Loading...</CenteredMessage>;
}
if (error) {
return <CenteredMessage>{error.message}</CenteredMessage>;
}
return children;
};
现在容器组件上的错误已经消失,但是 HandleQuery
组件上弹出了一个新的编译器错误:
Type error: Type '({ loading, error, children }: PropsWithChildren<HandleQueryProps>) => {} | null | undefined' is not assignable to type 'FunctionComponent<HandleQueryProps>'.
Type '{} | null | undefined' is not assignable to type 'ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<any, any, any>)> | null'.
Type 'undefined' is not assignable to type 'ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<any, any, any>)> | null'. TS2322
ReactNode 存在一个长期问题。我不了解具体细节,但它是 TypeScript 本身的东西 hard-wired,并且正在处理中。
无论哪种方式,解决方案都应该很简单。不要将 ReactNode 与功能组件一起使用 :) children
属性隐式包含在 React.FC 类型中。
返回 children 也有同样的问题。如果您愿意,可以通过包装到 <React.Fragment>
或 <div>
来克服它,但由于它只是一个类型错误,您可以说服 TypeScript 您知道自己在做什么 :)
import React, { ReactNode } from 'react';
import { CenteredMessage } from './centered-message';
export interface HandleQueryProps {
loading: boolean,
error?: Error,
}
export const HandleQuery: React.FC<HandleQueryProps> = ({ loading, error, children }) => {
if (loading) {
return <CenteredMessage>Loading...</CenteredMessage>;
}
if (error) {
return <CenteredMessage>{error.message}</CenteredMessage>;
}
return children as ReactElement<any>;
};
在这种情况下,如果我不回避某些事情,简单地定义类型 ReactElement
的 children
会更容易。
export interface HandleQueryProps {
loading: boolean,
error?: ApolloError,
children: ReactElement
}
对我来说,这个命令解决了问题:
rm -rf node_modules && rm yarn.lock && yarn
将 ReactNode
切换为 JSX.Element
解决了类型问题。
根据 the related github issue on React,建议对功能组件使用 JSX.Element
而不是 ReactNode
。
您可以在 typescript-cheatsheets/react page 中查看 JSX.Element
与 ReactNode
的详细信息。
我有一个名为 HandleQuery
的 React 组件,用于处理 Apollo GraphQL 查询的结果:
import React, { ReactNode } from 'react';
import { CenteredMessage } from './centered-message';
export interface HandleQueryProps {
loading: boolean,
error?: Error,
children: ReactNode
}
export const HandleQuery = ({ loading, error, children }: HandleQueryProps) => {
if (loading) {
return <CenteredMessage>Loading...</CenteredMessage>;
}
if (error) {
return <CenteredMessage>{error.message}</CenteredMessage>;
}
return children;
};
当此组件用于另一个组件时,它不会编译:
import React from 'react';
import { useQuery } from 'react-apollo-hooks';
import gql from 'graphql-tag';
import { HandleQuery } from '..';
import { MutationType } from '../../graphql-types';
import { AuthorsPanel } from './authors-panel';
import { GET_AUTHORS } from './authors-queries';
import { AuthorMutated } from './__generated__/AuthorMutated';
export class AuthorsContainer extends React.Component {
render() {
const { loading, error, data } = useQuery(GET_AUTHORS);
return (
<!-- THIS LINE PRODUCES A COMPILER ERROR -->
<HandleQuery loading={loading} error={error}>
<AuthorsPanel data={data} />
</HandleQuery>
);
}
}
使用上面的 HandleQuery
会产生以下错误:
Type error: JSX element type '{} | null | undefined' is not a constructor function for JSX elements. Type 'undefined' is not assignable to type 'Element | null'. TS2605
这是什么意思,我该如何摆脱它?
更新
将 AuthorsContainer 转换为函数组件并不能消除错误:
export const AuthorsContainer = () => {
const { loading, error, data } = useQuery(GET_AUTHORS);
return (
<HandleQuery loading={loading} error={error}>
<AuthorsPanel data={data} />
</HandleQuery>
);
};
更新 2 来自@FredyC 的实施建议:
import React from 'react';
import { CenteredMessage } from './centered-message';
export interface HandleQueryProps {
loading: boolean;
error?: Error;
}
export const HandleQuery: React.FC<HandleQueryProps> = ({
loading,
error,
children
}) => {
if (loading) {
return <CenteredMessage>Loading...</CenteredMessage>;
}
if (error) {
return <CenteredMessage>{error.message}</CenteredMessage>;
}
return children;
};
现在容器组件上的错误已经消失,但是 HandleQuery
组件上弹出了一个新的编译器错误:
Type error: Type '({ loading, error, children }: PropsWithChildren<HandleQueryProps>) => {} | null | undefined' is not assignable to type 'FunctionComponent<HandleQueryProps>'.
Type '{} | null | undefined' is not assignable to type 'ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<any, any, any>)> | null'.
Type 'undefined' is not assignable to type 'ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<any, any, any>)> | null'. TS2322
ReactNode 存在一个长期问题。我不了解具体细节,但它是 TypeScript 本身的东西 hard-wired,并且正在处理中。
无论哪种方式,解决方案都应该很简单。不要将 ReactNode 与功能组件一起使用 :) children
属性隐式包含在 React.FC 类型中。
返回 children 也有同样的问题。如果您愿意,可以通过包装到 <React.Fragment>
或 <div>
来克服它,但由于它只是一个类型错误,您可以说服 TypeScript 您知道自己在做什么 :)
import React, { ReactNode } from 'react';
import { CenteredMessage } from './centered-message';
export interface HandleQueryProps {
loading: boolean,
error?: Error,
}
export const HandleQuery: React.FC<HandleQueryProps> = ({ loading, error, children }) => {
if (loading) {
return <CenteredMessage>Loading...</CenteredMessage>;
}
if (error) {
return <CenteredMessage>{error.message}</CenteredMessage>;
}
return children as ReactElement<any>;
};
在这种情况下,如果我不回避某些事情,简单地定义类型 ReactElement
的 children
会更容易。
export interface HandleQueryProps {
loading: boolean,
error?: ApolloError,
children: ReactElement
}
对我来说,这个命令解决了问题:
rm -rf node_modules && rm yarn.lock && yarn
将 ReactNode
切换为 JSX.Element
解决了类型问题。
根据 the related github issue on React,建议对功能组件使用 JSX.Element
而不是 ReactNode
。
您可以在 typescript-cheatsheets/react page 中查看 JSX.Element
与 ReactNode
的详细信息。