【发布时间】:2023-04-09 20:37:01
【问题描述】:
我最近一直在试验符合 React、GraphQL、Apollo 和 Relay 的查询。
现在我有一个 GraphQL 后端,它有一个简单的 GraphQL 架构和一些连接查询,用于返回可以使用中继服务器规范进行分页的实体列表。
在前端,我发现自己在提出上述问题后会重复自己 代码通常如下所示:
type isDefined = <T>(value: T | null | undefined): value is T => value !== null && value !== undefined;
export const AppleListComponent: React.FC = () => {
const { data } = useAppleQuery(); // FWIW, generating this with graphql-code-generator
const apples = data && data.apples;
const appleNodes = apples && apples.edges.map(apple => (
apple ? apple.node : undefined
)).filter(apple => isDefined(apple));
return (
<div>
{appleNodes && appleNodes.map(apple => (
<p key={apple.text}>{apple.text}</p>
))}
</div>
);
};
由于 Relay 规范要求边和节点为 Nullable,因此检查存在性是必要的。
我发现自己经常重复这种从中继格式到简单节点数组格式的转换。 我决定看看是否可以创建一个辅助函数,该函数接受符合连接接口的内容并返回未定义或映射节点列表。
那个尝试看起来像这样:
type Maybe<T> = T | null;
type isDefined = <T>(value: T | null | undefined): value is T => value !== null && value !== undefined;
type Connection<T> = Maybe<{ edges: Array<Maybe<{ node: Maybe<T> }>>}>;
export const connectionToNodes = <T>(connection: Connection<T>): Maybe<T[]> => (
connection && connection.edges.map(edge => (
edge ? edge.node : undefined
)).filter(isDefined)
);
这让之前的组件变成
export const AppleListComponent: React.FC = () => {
const { data } = useAppleQuery();
const apples = data && data.apples;
const appleNodes = connectionToNodes(apples);
return (
<div>
{appleNodes && appleNodes.map(apple => (
<p key={apple.text}>{apple.text}</p>
))}
</div>
);
};
我的问题是我的 Connection 类型当然不完全匹配 加上我传入的类型,它有更多看起来像这样的属性:
Maybe<(
{ __typename?: 'AppleConnection' }
& { edges: Array<Maybe<(
{ __typename?: 'AppleEdge' }
& { node: Maybe<{ __typename?: 'AppleType' }
& { __typename?: 'QuestionType' }
& Pick<QuestionType, 'text'>
> }
)>> }
)>
所以我最终会收到关于任何类型问题的错误,以及
我传递给connectionToNodes 的内容与指定的类型不匹配。
我的直觉是我需要说我的类型 T 是其他东西的子类型 - 的
申请课程我不在乎是Apple还是Pear
连接/边缘/节点,但我希望它最终被推断出来 - 任何建议
如何实现这一目标?
【问题讨论】:
标签: reactjs typescript graphql react-apollo relayjs