在应用apollo的graphql()后缺少数据通道导致的流程类型错误HOC

问题描述:

在阅读post之后,有关向一个graphql注入的对象添加流类型是多么容易,我认为我会试一试。由于6月份的这篇文章已经升级到0.53,我无法获得使用类组件的基本示例。我不确定这是否是react-apollo的原始定义中的升级或其他问题。在应用apollo的graphql()后缺少数据通道导致的流程类型错误HOC

问题:如何让组件的类版本工作?

这里是我的示例代码:

// @flow 
import * as React from 'react'; 
import gql from 'graphql-tag'; 
import { graphql } from 'react-apollo'; 
import type { OperationComponent, QueryOpts } from 'react-apollo'; 

const HERO_QUERY = gql` 
    query GetCharacter($episode: Episode!) { 
    hero(episode: $episode) { 
     name 
     id 
     friends { 
     name 
     id 
     appearsIn 
     } 
    } 
    } 
`; 
type Hero = { 
    name: string, 
    id: string, 
    appearsIn: string[], 
    friends: Hero[] 
}; 
type Response = { 
    hero: Hero 
}; 

type Props = { 
    data: QueryOpts & Response, 
} 

const withCharacter: OperationComponent<Response, Props> = graphql(HERO_QUERY, { 
    options:() => ({ 
    variables: { episode: 'JEDI' }, 
    }), 
}); 

class TestClass extends React.Component<Props> { 
    render() { 
    const { loading, error, hero } = this.props.data; 
    if (loading) return <div>Loading</div>; 
    if (error) return <h1>ERROR</h1>; 
    return <div>My hero: {hero.name}</div>; 
    } 
} 

const TestFn = ({ data: { loading, error, hero } }) => { 
    if (loading) return <div>Loading</div>; 
    if (error) return <h1>ERROR</h1>; 
    return <div>My hero: {hero.name}</div>; 
}; 

export const clss = withCharacter(TestClass); // ERROR! 
export const fn = withCharacter(TestFn); // Works fine 

这里是FR的OperationComponent类型的定义,它的核心部件从definition与更新相匹配的0.53流量风格:

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

export type MutationFunc<TResult> = (
    opts: MutationOpts, 
) => Promise<ApolloQueryResult<TResult>>; 

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

export interface OperationComponent< 
    TResult: Object = {}, 
    TOwnProps: Object = {}, 
    TMergedProps = ChildProps<TOwnProps, TResult>, 
> { 
    (
    component: 
     | StatelessComponent<TMergedProps> 
     | Class<React$Component<any, TMergedProps, any>>, 
): Class<React$Component<TOwnProps, void>>, 
} 

declare export function graphql<TResult, TProps, TChildProps>(
    document: DocumentNode, 
    operationOptions?: OperationOption<TProps, TResult>, 
): OperationComponent<TResult, TProps, TChildProps>; 

当我运行flow focus-check src/test.js(v。0.53.1)我得到:

Error: src/test.js:42 
42:  const { loading, error, hero } = this.props.data; 
       ^^^^^^^ property `loading`. Property cannot be accessed on any member of intersection type 
42:  const { loading, error, hero } = this.props.data; 
              ^^^^^^^^^^^^^^^ intersection 
    Member 1: 
    31: data: QueryOpts & Response, 
       ^^^^^^^^^ QueryOpts 
    Error: 
    42:  const { loading, error, hero } = this.props.data; 
        ^^^^^^^ property `loading`. Property not found in 
    31: data: QueryOpts & Response, 
       ^^^^^^^^^ QueryOpts 
    Member 2: 
    31: data: QueryOpts & Response, 
          ^^^^^^^^ Response 
    Error: 
    42:  const { loading, error, hero } = this.props.data; 
        ^^^^^^^ property `loading`. Property not found in 
    31: data: QueryOpts & Response, 
          ^^^^^^^^ object type 

Error: src/test.js:42 
42:  const { loading, error, hero } = this.props.data; 
          ^^^^^ property `error`. Property cannot be accessed on any member of intersection type 
42:  const { loading, error, hero } = this.props.data; 
              ^^^^^^^^^^^^^^^ intersection 
    Member 1: 
    31: data: QueryOpts & Response, 
       ^^^^^^^^^ QueryOpts 
    Error: 
    42:  const { loading, error, hero } = this.props.data; 
          ^^^^^ property `error`. Property not found in 
    31: data: QueryOpts & Response, 
       ^^^^^^^^^ QueryOpts 
    Member 2: 
    31: data: QueryOpts & Response, 
          ^^^^^^^^ Response 
    Error: 
    42:  const { loading, error, hero } = this.props.data; 
          ^^^^^ property `error`. Property not found in 
    31: data: QueryOpts & Response, 
          ^^^^^^^^ object type 

Error: src/test.js:55 
55: export const clss = withCharacter(TestClass); 
             ^^^^^^^^^ class type: TestClass. This type is incompatible with 
      v------------------------------- 
123:  | StatelessComponent<TMergedProps> 
124:  | Class<React$Component<any, TMergedProps, any>>, 
      -----------------------------------------------^ union: type application of polymorphic type: type `StatelessComponent` | class type: type application of identifier `React$Component`. See: node_modules/react-apollo/react-apollo.umd.js.flow:123 
    Member 1: 
    123:  | StatelessComponent<TMergedProps> 
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type application of polymorphic type: type `StatelessComponent`. See: node_modules/react-apollo/react-apollo.umd.js.flow:123 
    Error: 
    123:  | StatelessComponent<TMergedProps> 
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function type. Callable signature not found in. See: node_modules/react-apollo/react-apollo.umd.js.flow:123 
    55: export const clss = withCharacter(TestClass); 
             ^^^^^^^^^ statics of TestClass 
    Member 2: 
    124:  | Class<React$Component<any, TMergedProps, any>>, 
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ class type: type application of identifier `React$Component`. See: node_modules/react-apollo/react-apollo.umd.js.flow:124 
    Error: 
    124:  | Class<React$Component<any, TMergedProps, any>>, 
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type application of identifier `React$Component`. Too many type arguments. Expected at most 2. See: node_modules/react-apollo/react-apollo.umd.js.flow:124 
    29: declare class React$Component<Props, State = void> { 
            ^^^^^^^^^^^^ See type parameters of definition here. See lib: /tmp/flow/flowlib_1135e841/react.js:29 


Found 3 errors 

我试着加入一些改进0.53,但没有无济于事:

export interface OperationComponent< 
    TResult: Object = {}, 
    TOwnProps: Object = {}, 
    TMergedProps = ChildProps<TOwnProps, TResult>, 
> { 
    (
    component: React$ComponentType<TMergedProps> 
): React$ComponentType<TOwnProps>, 
} 

哦...不对查询,应该是QueryProps而不是QueryOpts

// @flow 
import * as React from 'react'; 
import gql from 'graphql-tag'; 
import { graphql } from 'react-apollo'; 
import type { OperationComponent, QueryProps } from 'react-apollo'; 

const HERO_QUERY = gql` 
    query GetCharacter($episode: Episode!) { 
    hero(episode: $episode) { 
     name 
     id 
     friends { 
     name 
     id 
     appearsIn 
     } 
    } 
    } 
`; 

type Hero = { 
    name: string, 
    id: string, 
    appearsIn: string[], 
    friends: Hero[] 
}; 

type Response = { 
    hero: Hero 
}; 

type Props = { 
    data: QueryProps & Response, 
    mutate: any, 
} 

const withCharacter: OperationComponent<Response, Props> = graphql(HERO_QUERY, { 
    options:() => ({ 
    variables: { episode: 'JEDI' }, 
    }), 
}); 

class TestClass extends React.Component<Props> { 
    render() { 
    const { loading, error, hero } = this.props.data; 
    if (loading) return <div>Loading</div>; 
    if (error) return <h1>ERROR</h1>; 
    return <div>My hero: {hero.name}</div>; 
    } 
} 

const TestFn = ({ data: { loading, error, hero } }) => { 
    if (loading) return <div>Loading</div>; 
    if (error) return <h1>ERROR</h1>; 
    return <div>My hero: {hero.name}</div>; 
}; 

export const clss = withCharacter(TestClass); // Works 
export const fn = withCharacter(TestFn); // Works