将 React.Components 与 apollo-client 和 TypeScript 一起使用

Using React.Components with apollo-client and TypeScript

我正在尝试使用 apollo-client 和 TypeScript 构建一个简单的 React 组件。

该组件只是查询文章列表并显示它们。代码如下:

import * as React from 'react';
import graphql from "react-apollo/graphql";
import { ARTICLES_FEED } from "../schemas/queries";
import { Article, ArticlesFeedResponse } from "../schemas/results";
import { ChildProps } from "react-apollo/types";

const AppQL = graphql<ArticlesFeedResponse, {}>(ARTICLES_FEED);

class App extends React.Component<ChildProps<{}, ArticlesFeedResponse>, {}> {
    render() {
        const { loading, feed, error } = this.props.data;

        if (loading) return <div>loading</div>;
        if (error) return <div>{ error }</div>;
        return (
            <React.Fragment>
                <h1>It works!</h1>
                {this.props.data && feed.map( (article:Article) => (
                    <div>{article.shortText}</div>
                ))}
            </React.Fragment>
        );
    }
}

export default AppQL(App);

schemas/results:

export interface Article {
    id: string,
    shortText: string,
    publicationDate: string
}

export type ArticlesFeedResponse = {
  feed: Article[];
}

schemas/queries:

import gql from 'graphql-tag'

export const ARTICLES_FEED = gql`
    query ArticlesFeed {
        feed {
            id
            shortText
            publicationDate
        }
    }
`;

尽管如此,签名匹配,但我仍然收到错误消息:

Type '(QueryProps<OperationVariables> & Partial<ArticlesFeedResponse>) | undefined' has no property 'loading' and no string index signature.

我不明白发生了什么 - 导入的类型是:

儿童道具:

export declare type ChildProps<P, R> = P & {
    data?: QueryProps & Partial<R>;
    mutate?: MutationFunc<R>;
};

查询道具:

export interface QueryProps<TVariables = OperationVariables> {
    error?: ApolloError;
    networkStatus: number;
    loading: boolean;
    variables: TVariables;
    fetchMore: (fetchMoreOptions: FetchMoreQueryOptions & FetchMoreOptions) => Promise<ApolloQueryResult<any>>;
    refetch: (variables?: TVariables) => Promise<ApolloQueryResult<any>>;
    startPolling: (pollInterval: number) => void;
    stopPolling: () => void;
    subscribeToMore: (options: SubscribeToMoreOptions) => () => void;
    updateQuery: (mapFn: (previousQueryResult: any, options: UpdateQueryOptions) => any) => void;
}

所以 ChildProps 应该同时包含 loadingerror 属性。我想错误来自 | undefined 部分,但我不明白为什么这个联合会出现。

有什么建议吗?

P. S. 如果我不从 react-apollo/types 导入默认值 ChildProps,而是使用这个更新版本:

type ChildProps<P, R> = P & {
    data: QueryProps & R;
    mutate?: MutationFunc<R>;
};

我的代码正在运行。我仍然不明白的是 - 我做错了什么或者这是 react-apollo/types 包中的错误?

graphql 类型注释采用 <ParentProps, QueryResponse, Variables>。你通过了

graphql<ArticlesFeedResponse, {}>(ARTICLES_FEED)

你什么时候应该通过它

graphql<{} ArticlesFeedResponse>(ARTICLES_FEED)

其次,如您所述,ChildProps 注释指出 data 可以是 undefined。考虑到这一点,一切都应该进行类型检查。

class App extends React.Component<ChildProps<{}, ArticlesFeedResponse>, {}> {
  render() {
    if (!this.props.data) {
      return;
    }

    const { loading, feed, error } = this.props.data;

    if (loading) return <div>loading </div>;
    if (error) return <div>{error} </div>;

    return (
      <React.Fragment>
      <h1>It works!</h1>
        {
          feed && feed.map((article: Article) => (
            <div>{ article.shortText } </div>
          ))
        }
      </React.Fragment>
    );
  }
}

或者,标记 const { loading, feed, error } = this.props.data!; 以告诉类型检查器它不会是未定义的。 AFAIK,data 道具永远不应该是未定义的,所以你可以安全地将它标记为存在 this.props.data!,...也许 ChildProps 注释是 incorrect/a 错误?值得注意的是,example docs 不进行类型检查。

针对 react-apollo@2.1.9

进行了测试