使用 react-apollo Query 组件 render prop 时的流程错误
Flow error when using react-apollo Query component render prop
我有以下代码:
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>
我从流程中得到以下错误:
Error:(151, 27) Cannot get 'data.posts' because property 'posts' is missing in object type [1].
知道为什么吗?
我确实用了flow-typed
顺便把apollo-client_v2.x.x.js
加到我的项目里
如何做一个可复现的例子并研究问题
所以我们在分析这些类型时需要做的第一件事就是去查找 flow-typed repo. I went ahead a copy-pasted the react-apollo typedefs 中的 typedefs 到流中。org/try,稍微修改它们(添加一个 any
在某处,将 gql
设置为 any
),并且能够复制您的错误:
(Try - 滚动到代码底部)
引用 relevant lines of the QueryRenderProps
type,我们可以看到流抛出错误的原因:
{
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;
...
}
不幸的是,由于这些链接的极端长度和 Whosebug 对答案长度的限制,我不得不在 中继续我的回答。我想这个答案可以作为如何开始调试问题的解释。
问题的解决
接解释如何制作
的答案
所以看起来 react-apollo 的这一部分没有以直接访问 data
内容的方式输入。好的,没关系,我们可以采纳他们关于解构的建议并检查空数据。同时,我们还可以将 id
属性 添加到 Post
类型,这样流程就不会再抱怨了:
(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.
断言所需的类型
我有以下代码:
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>
我从流程中得到以下错误:
Error:(151, 27) Cannot get 'data.posts' because property 'posts' is missing in object type [1].
知道为什么吗?
我确实用了flow-typed
顺便把apollo-client_v2.x.x.js
加到我的项目里
如何做一个可复现的例子并研究问题
所以我们在分析这些类型时需要做的第一件事就是去查找 flow-typed repo. I went ahead a copy-pasted the react-apollo typedefs 中的 typedefs 到流中。org/try,稍微修改它们(添加一个 any
在某处,将 gql
设置为 any
),并且能够复制您的错误:
(Try - 滚动到代码底部)
引用 relevant lines of the QueryRenderProps
type,我们可以看到流抛出错误的原因:
{
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;
...
}
不幸的是,由于这些链接的极端长度和 Whosebug 对答案长度的限制,我不得不在
问题的解决
接解释如何制作
所以看起来 react-apollo 的这一部分没有以直接访问 data
内容的方式输入。好的,没关系,我们可以采纳他们关于解构的建议并检查空数据。同时,我们还可以将 id
属性 添加到 Post
类型,这样流程就不会再抱怨了:
(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.
断言所需的类型