我有一个名为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会产生以下错误:

类型错误:JSX元素类型"{}|null | undefined"不是JSX元素的构造函数.

这意味着什么?我怎样才能摆脱它?

Update

将AuthorsContainer转换为函数组件并不能消除错误:

export const AuthorsContainer = () => {
    const { loading, error, data } = useQuery(GET_AUTHORS);
    return (
        <HandleQuery loading={loading} error={error}>
            <AuthorsPanel data={data} />
        </HandleQuery>
    );
};

Update 2

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本身固有的东西,正在开发中.

无论如何,解决方案都应该很简单.不要将ReactNode与功能组件一起使用:)childrenprops 隐式包含在React中.FC类型.

回国的子元素也面临同样的问题.如果您愿意,可以通过将其包装成<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>;
};

Typescript相关问答推荐

具有泛型类型和缺省值的键

如何重构长联合类型?

Angular 15使用react 式表单在数组内部创建动态表单数组

TypeScrip:从对象中提取和处理特定类型的键

保护函数调用,以便深度嵌套的对象具有必须与同级属性函数cargument的类型匹配的键

try 呈现应用程序获取-错误:动作必须是普通对象.使用自定义中间件进行MySQL操作

根据类型脚本中的泛型属性 Select 类型

有没有办法在Zod中使用跨字段验证来判断其他字段,然后呈现条件

在打字应用程序中使用Zod和Reaction-Hook-Forms时显示中断打字时出错

错误TS7030:并非所有代码路径都返回值.";由tsfig.json中的";Strong";:False引起

如何正确地将元组表格输入到对象数组实用函数(如ZIP)中,避免在TypeScrip 5.2.2中合并所有值

带有';的类型脚本嵌套对象可选属性错误满足';

如何调整项目数组,但允许权重影响顺序

我的类型谓词函数不能像我预期的那样工作.需要帮助了解原因

如何在Vue动态类的上下文中解释错误TS2345?

使用受保护的路由和入门来响应路由

为什么我的 Typescript 函数中缺少 void 隐式返回类型?

TS 条件类型无法识别条件参数

验证返回值是否满足函数签名中的条件类型

无法从其他子接口键名扩展接口