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

时间:2018-01-25 11:03:44

标签: typescript react-apollo apollo-client

我尝试使用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);

模式/结果:

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

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

模式/查询:

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.

我不知道发生了什么 - 导入的类型是:

ChildProps:

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

QueryProps:

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.如果我不从ChildProps导入默认react-apollo/types,而是使用此更新版本:

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

我的代码正在运行。我还没有得到的是 - 我做错了什么或者这是react-apollo/types包中的错误?

1 个答案:

答案 0 :(得分:1)

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注释不正确/有错误?值得注意的是,example docs不会进行类型检查。

针对react-apollo@2.1.9

进行了测试