我正在使用Reason-Apollo从我的服务器解析一个非常嵌套的 GraphQL 响应。我无法解析从我的 GraphQL 服务器返回的毛茸茸的选项树(我正在使用 django-graphene)。
这是使用 Reason Apollo 的 GraphQL 查询和 Reason React 模块:
module GroupQuery = [%graphql {|
query GetChatGroup($chatGroupId: ID!){
chatGroup(id: $chatGroupId) {
id
users {
edges {
node {
id
name
isCurrentUser
}
}
}
messages {
edges {
node {
id
text
author {
name
abbreviation
photoUrl
isCurrentUser
}
}
}
}
}
}
|}];
/*eventually will be a reducerComponent*/
let component = ReasonReact.statelessComponent("RechatWindow");
module Query = RechatApollo.Instance.Query;
let parseMessages = chatGroup =>
switch chatGroup {
| Some(chatGroup) =>
switch chatGroup##messages {
| Some(messages) =>
let edges = messages##edges;
switch edges {
| Some(edges) =>
let parsedNodes =
Js.Array.map(
node =>
switch node {
| Some(node) =>
let id = node##id;
let text = node##text;
let author = node##author;
switch (id, text, author) {
| (Some(id), Some(text), Some(author)) =>
let name = author##name;
let abbrev = author##abbreviation;
let isCurrentUser = author##isCurrentUser;
switch (name, abbrev, isCurrentUser) {
| (Some(name), Some(abbrev), Some(isCurrentUser)) =>
id ++ " - " ++ text ++ " - " ++ name ++ " - " ++ abbrev ++ " - "
| _ => "Error retrieving message 3"
};
| _ => "Error retrieving message 2"
};
| _ => "Error retrieving message 1"
},
edges
);
parsedNodes;
| None => [||]
};
| None => [||]
};
| None => [||]
};
let make = (_children) => {
...component,
render: (_) => {
let unexpectedError = <div> (ReasonReact.stringToElement("There was an internal error")) </div>;
let groupQuery = GroupQuery.make(~chatGroupId="Q2hhdEdyb3VwVHlwZTox", ());
<Query query=groupQuery>
...((response, parse) => {
switch response {
| Loading => <div> (ReasonReact.stringToElement("Loading")) </div>
| Failed(error) => <div> (ReasonReact.stringToElement(error)) </div>
| Loaded(result) => {
let chatGroup = parse(result)##chatGroup;
let parsedMessages = parseMessages(chatGroup);
<ul>
(
ReasonReact.arrayToElement(
Array.map(message => <li> (ste(message)) </li>, parsedMessages)
)
)
</ul>;
}
}
})
</Query>
}
};
这是来自 GraphiQL 的 GraphQL 查询的返回数据:
{
"data": {
"chatGroup": {
"id": "Q2hhdEdyb3VwVHlwZTox",
"users": {
"edges": [
{
"node": {
"id": "VXNlclR5cGU6MzQ=",
"name": "User 1",
"isCurrentUser": false
}
},
{
"node": {
"id": "VXNlclR5cGU6MQ==",
"name": "User 2",
"isCurrentUser": true
}
}
]
},
"messages": {
"edges": [
{
"node": {
"id": "Q2hhdE1lc3NhZ2VUeXBlOjE=",
"text": "my first message",
"author": {
"name": "User 1",
"abbreviation": "U1",
"photoUrl": "",
"isCurrentUser": true
}
}
}, ...
我在某处有语法错误...
137 ┆ | Loaded(result) => {
138 ┆ let chatGroup = parse(result)##chatGroup;
139 ┆ let parsedMessages = parseMessages(chatGroup);
140 ┆ <ul>
141 ┆ (
This has type:
option(Js.t({. id : string,
messages : option(Js.t({. edges : array(option(Js.t(
{. node :
option(
Js.t(
{. author :
Js.t(
{. abbreviation :
option(
string),
isCurrentUser :
option(
Js.boolean),
name :
option(
string),
photoUrl :
option(
string) }),
id :
string,
text :
string })) }))) })),
users : option(Js.t({. edges : array(option(Js.t({. node :
option(
Js.t(
{. id :
string,
isCurrentUser :
option(
Js.boolean),
name :
option(
string) })) }))) })) }))
But somewhere wanted:
option(Js.t({.. messages : option(Js.t({.. edges : option(Js.Array.t(
option(
Js.t({.. author :
option(
Js.t(
{.. abbreviation :
option(
string),
isCurrentUser :
option('a),
name :
option(
string) })),
id :
option(
string),
text :
option(
string) })))) })) }))
Types for method edges are incompatible
我的直接问题是:这里的错误是什么?
在更深层次上,解析所有这些选项以呈现所需的响应似乎通常会产生非常不清楚的代码。那么在使用 ReasonML / OCaml 时,围绕 JS 中解析选项的常见范式是什么?是否有一种惯用的方式来获得大部分时间都会出现的所有选项?我应该创建对象类型还是记录类型并解析成这些类型,然后从“已知”对象或记录结构中呈现?
或者也许我graphql_schema.json
和端点需要更多必需的选项?
另外,我正在使用 Relay 的 GraphQL 约定,edges { node { ... node fields ... } }
如果有任何边,那么应该至少有一个节点。使用中继式 GraphQL 时,有什么方法可以减少选项的冗长性?