代码之家  ›  专栏  ›  技术社区  ›  Sammy

使用React Apollo查询组件呈现属性时出现流错误

  •  1
  • Sammy  · 技术社区  · 7 年前

    我有以下代码:

    import { Query } from 'react-apollo';
    
    type Post = {
      id: string
    };
    
    interface Data {
      posts: Array<Post>;
    }
    
    class PostsQuery extends Query<Data> {}

    使用上述方法时:

    <PostsQuery query={POSTS_QUERY}>
      {({ loading, data }) => {
        ...
        {data.posts.map(...)}
        ...
      }
    </PostsQuery>

    我从flow得到以下错误:

    Error:(151, 27) Cannot get 'data.posts' because property 'posts' is missing in object type [1].

    知道为什么吗?

    我确实用过 flow-typed 添加 apollo-client_v2.x.x.js 顺便说一下我的项目

    2 回复  |  直到 7 年前
        1
  •  1
  •   James Kraus    7 年前

    如何做一个可复制的例子并研究这个问题

    所以在分析这些类型时,我们需要做的第一件事是在 flow-typed repo .我接着写了一份 react-apollo typedefs 在flow.org/try中,稍微修改了它们(添加了 any 某处,集合 gql 任何 ,并能够复制您的错误:

    ( Try -滚动到底部以获取代码)

    引用 relevant lines of the QueryRenderProps type ,我们可以看到flow抛出错误的原因:

    {
         data: TData | {||} | void,
         ...
    }
    

    看起来数据可以是 TData (可能是您想要的)、空对象或未定义的对象。把这个和 typescript typings for react-apollo ,我们可以看到为什么类型是这样的:

    {
        ...
        // we create an empty object to make checking for data
        // easier for consumers (i.e. instead of data && data.user
        // you can just check data.user) this also makes destructring
        // easier (i.e. { data: { user } })
        // however, this isn't realy possible with TypeScript that
        // I'm aware of. So intead we enforce checking for data
        // like so result.data!.user. This tells TS to use TData
        // XXX is there a better way to do this?
        data: TData | undefined;
        ...
    }
    

    不幸的是,由于这些链接的极端长度和stackoverflow对答案长度的限制,我不得不在 another answer .我想这个答案可以解释如何开始调试这个问题。

        2
  •  3
  •   James Kraus    7 年前

    问题的解决办法

    从答案继续解释如何 verifiable example and research the problem.

    所以看起来React Apollo的这一部分并没有以这样的方式输入,使得访问 data 内容直截了当。好吧,没关系,我们可以采纳他们关于解构的建议并检查空数据。同时,我们还可以添加 id 财产 Post 输入so flow停止抱怨:

    ( Try -滚动至底部以获取相关代码)

    type Post = {
      id: string,
      title: string;
    };
    
    ...snip...
    
    // Look ma, no errors
    class Search extends React.Component<{}> {
      render = () => (
        <PostsQuery query={QUERY}>
        {({ loading, error, data }) => {
          if (error) {
            return <p>Error</p>
          }
          if (loading) return <p>Loading</p>
          const nonNullData = (data || {})
          const dataWithAllPosts = {allPosts: [], ...nonNullData}
          const {allPosts} = dataWithAllPosts
          if (allPosts.length == 0) {
            return <p>Empty response or something</p>
          }
          return (
              <div>
                {allPosts.map(post => {
                  return <div key={post.id}>{post.title}</div>;
                })}
              </div>
          );
        }}
        </PostsQuery>
      );
    }
    

    我不熟悉React Apollo库,所以我不确定您想如何处理没有帖子的情况。我刚刚添加了一条如上所示的消息。完全有可能这个案子从来没有发生过(再说一次,你比我更清楚)。如果是这样的话,您可能希望跳过上面的一些步骤,只使用 cast through any 是的。