如何使用 Relay 处理服务器端输入验证?
Posted
技术标签:
【中文标题】如何使用 Relay 处理服务器端输入验证?【英文标题】:How to tackle server-side input validation using Relay? 【发布时间】:2016-08-30 21:44:29 【问题描述】:我有以下有效的 GraphQL 操作:
GraphQL 突变:
mutation CreateUserMutation ($input: CreateUserInput!)
createUser(input: $input)
clientMutationId
userEdge
node
email
username
,
validationErrors
id
email
GraphQL 突变响应:
"data":
"createUser":
"clientMutationId": "112",
"userEdge":
"node":
"email": "prasath112@example.com",
"username": "soosap112"
,
"validationErrors":
"id": "create-user-validation-errors",
"email": [
"Email looks not so good."
]
到目前为止一切顺利,我的 GraphQL 响应的 validationErrors
是键值对的对象,其中 value 始终是来自服务器的输入验证错误消息数组特定的输入字段(即'email': ['email is taken', 'email is on blacklist']
)。
下一步(这是我需要帮助的地方)-如何在 Relay 客户端存储中使用该数据?换句话说,要如何让我的组件中的 validationErrors 成为this.props.validationErrors
?
CreateUserMutation.js
import Relay from 'react-relay';
export class CreateUserMutation extends Relay.Mutation
getMutation()
return Relay.QL`
mutation
createUser
`;
getVariables()
return
email: this.props.email,
username: this.props.username,
password: this.props.password,
;
getFatQuery()
return Relay.QL`
fragment on CreateUserPayload @relay(pattern: true)
userEdge,
validationErrors,
viewer userConnection
`;
getConfigs()
return [
type: 'FIELDS_CHANGE',
fieldIDs:
validationErrors: 'create-user-validation-errors',
,
,
type: 'RANGE_ADD',
parentName: 'viewer',
parentID: this.props.viewer.id,
connectionName: 'userConnection',
edgeName: 'userEdge',
rangeBehaviors:
// When the ships connection is not under the influence
// of any call, append the ship to the end of the connection
'': 'append',
// Prepend the ship, wherever the connection is sorted by age
// 'orderby(newest)': 'prepend',
,
,
];
这是我的尝试:首先,我可以使用 getConfigs RANGE_ADD
将 user edge 消耗到我的 Relay 客户端存储中。由于我的validationErrors
对象没有实现连接模型,所以FIELDS_CHANGE
在我的例子中似乎是唯一合理的类型。我正在尝试模拟 Relay 似乎需要使用“create-user-validation-errors”作为唯一 ID 填充客户端存储的 dataID。
这是我的 React 组件中的一个 sn-p,用于使示例完整。
class App extends React.Component
static propTypes =
limit: React.PropTypes.number,
viewer: React.PropTypes.object,
validationErrors: React.PropTypes.object,
;
static defaultProps =
limit: 5,
validationErrors:
id: 'create-user-validation-errors',
,
;
handleUserSubmit = (e) =>
e.preventDefault();
Relay.Store.commitUpdate(
new CreateUserMutation(
email: this.refs.newEmail.value,
username: this.refs.newUsername.value,
password: this.refs.newPassword.value,
viewer: this.props.viewer,
)
);
;
如何使用 Relay 从 React 组件中的 GraphQL 响应中使用基于非连接模型的信息片段?最小的工作示例会很棒。
您知道使用 GraphQL 和 Relay 进行服务器端输入验证的更好方法吗?
【问题讨论】:
【参考方案1】:突变要么成功,要么失败。我通常设计客户端突变的胖查询和配置,牢记成功案例。处理失败的情况,mutation 的回调函数就足够了。
如何使用 Relay 从 React 组件中的 GraphQL 响应中使用基于非连接模型的信息?
据我所知,有两种方法。
1) 使用FIELDS_CHANGE
输入客户端突变代码的getConfigs
函数: 当我们需要更新Relay store 中的数据以响应突变的结果时,通常使用这个。代码如下所示:
getFatQuery()
return Relay.QL`
fragment on CreateUserPayload
...
...
viewer
userCount,
`;
getConfigs()
return [
type: 'FIELDS_CHANGE',
fieldIDs:
viewer: this.props.viewer.id,
,
,
...
...
];
在您的情况下,如果您想将 validationErrors
作为 Relay 存储的一部分进行更新,请将其作为道具传递并拥有 validationErrors: this.props.validationErrors.id
。
2) 使用突变的回调函数: 当我们只需要一些不应该影响 Relay 存储中数据的信息时,这是一个不错的选择。代码如下:
const mutation = new CreateUserMutation(
email: this.state.email,
username: this.state.username,
password: this.state.password,
viewer: this.props.viewer,
);
const onSuccess = (response) =>
// If you have both successful data update and some other extra info, you
// can have, say `response.warnings`. The server sends `warnings` in the
// response object.
;
const onFailure = (transaction) =>
// This is the most appropriate place for dealing with errors.
var error = transaction.getError();
// Get the errors!
;
Relay.Store.commitUpdate(mutation, onSuccess, onFailure);
您知道使用 GraphQL 和 Relay 进行服务器端输入验证的更好方法吗?
GraphQL 和 Relay 支持的基本输入验证目前仅限于使用 GraphQLNonNull
和预期类型,例如 names: new GraphQLNonNull(GraphQLString)
。因此,如果我们为 name 传递一个整数,则突变将失败并提供相应的错误消息。
对于其他类型的验证,服务器端突变中的mutateAndGetPayload
函数是一个好地方,我们可以在其中应用自己的逻辑。
Konstantin Tarkus 在 GraphQL 突变中的输入验证上有 an excellent article。
【讨论】:
嘿,这正是我想要的——感谢您的澄清。我已阅读引用的文章。 Tarkus 区分系统级错误和应用程序级错误。 系统级错误可以在onFailure
回调中很好地处理,应用级错误应该在mutateAndGetPayload
中处理——这就是我从中得到的。
@soosap 找到了一个 npm 模块 graphql-errors,它为客户端屏蔽了 GraphQL 系统级别 错误。我自己没用过。认为您可能感兴趣。
transaction.getError()
是否返回对象?
@maxwell: 是的,transaction.getError()
返回一个像 "source":"data":"mutation_name":null,"errors":["message":"error_message_thrown_in_server","locations":["line":1,"column":68]]
这样的对象
阅读github.com/facebook/relay/issues/777 似乎@soosap 解决方案更好,他可以使用查询配置REQUIRED_CHILDREN 然后与响应有效负载进行交互以上是关于如何使用 Relay 处理服务器端输入验证?的主要内容,如果未能解决你的问题,请参考以下文章