我正在尝试编写一个允许服务器端验证的中继突变。例如具有该名称的记录已经存在。
以下是我的GraphQL变异。
/* @flow weak */
import {mutationWithClientMutationId,offsetToCursor} from "graphql-relay";
import {GraphQLString, GraphQLList, GraphQLNonNull} from "graphql";
import NominationConnection from '../NominationsConnection';
import ViewerType from '../../../types/ViewerType';
import Helper from '../../../helper/helper';
import Nomination from '../../../model/Nomination';
const mongo = require('mongodb');
/**
* mutationWithClientMutationId()
*
* This helper function helps us create Relay-compliant GraphQL mutations it takes an object with the following params
* { name: "", inputField: { }, outputFields: {}, mutateAndGetPayload: function({}) }
*
*/
export default mutationWithClientMutationId({
// Name of the Mutation
name: "Nomination_Add",
// Describes the fields that should be used when invoking the mutation
inputFields: {
name: {
type: new GraphQLNonNull(GraphQLString)
},
description: {
type: new GraphQLNonNull(GraphQLString)
},
books: {
type: new GraphQLList(GraphQLString)
}
},
// response that will be sent back when the mutation is complete
outputFields: {
NominationsEdge: {
type: NominationConnection.edgeType,
resolve: ( {local_id}, { ...args }, context, { rootValue: objectManager } ) =>
{
//RT: local_id is the object that was inserted into DB.;
let nomination = local_id[0];
console.log("nomination: ", nomination);
if(nomination.Errors.length > 0){
return objectManager.getListBy('Nomination', nomination, {}, {})
.then((arr) => {
return ( {
cursor: null,
node: nomination,
} )
})
}else {
let an_Object;
return objectManager.getOneByParam('Nomination', nomination, {_id: nomination.id})
.then((retrieved_Object) => {
an_Object = retrieved_Object;
})
.then(() => objectManager.getListBy('Nomination', an_Object, {}, {}, objectManager.getViewerUserId()))
.then((arr) => {
return ( {
cursor: Helper.cursorForObjectInConnection(arr, an_Object, "id"),
node: an_Object,
} )
})
;
}
}
},
Viewer: {
type: ViewerType,
resolve: (parent, args, context, {rootValue: objectManager}) => objectManager.getOneById('User', objectManager.getViewerUserId())
}
},
mutateAndGetPayload: ({name, description, books}, context, {rootValue: objectManager}) => {
if(!books){
books = [];
}
return objectManager.add('Nomination', {
name,
description,
books
}, {name: name}).then((local_id) => ( {local_id} ));
}
});
以下是我的接力突变。
/* @flow weak */
import Relay from 'react-relay';
export default class Nomination_addMutation extends Relay.Mutation {
// static fragments = {
// Viewer: () => Relay.QL`
// fragment on Viewer {
// id,
// }
// `,
// };
getMutation() {
return Relay.QL`mutation{Nomination_Add}`;
}
getFatQuery() {
return Relay.QL`
fragment on Nomination_AddPayload {
NominationsEdge,
Viewer {
Nominations(first:500){
edges{
node{
id,
Name,
Description
}
}
}
}
}
`;
}
getConfigs() {
return [{
type: 'RANGE_ADD',
parentName: 'Viewer',
parentID: this.props.Viewer.id,
connectionName: 'Nominations',
edgeName: 'NominationsEdge',
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',
},
}];
}
getVariables() {
return {
name: this.props.name,
description: this.props.description,
books: this.props.books,
};
}
getOptimisticResponse() {
return {
Nomination: {
name: this.props.name,
description: this.props.description,
books: this.props.books,
},
Viewer: {
id: this.props.Viewer.id,
},
};
}
}
以下是我如何致电它。
Relay.Store.commitUpdate(
new Nomination_Add( {name: fields.name , description: fields.desc ,Viewer:this.props.Viewer}),
{
onSuccess: response => {
console.log(response);
console.log(response.Nomination_Add);
},
}
);
我的响应对象只有Viewer.id和clientmuationID。当我通过graphql调用此突变时,它看起来像这样。
mutation{
Nomination_Add(input:{name:"test", description:"test", clientMutationId:"2"}){
NominationsEdge{
node{
Name,
Description,
Errors {
Message
}
Books{
Title
}
}
}
}
}
对此作出回应。
{
"data": {
"Nomination_Add": {
"NominationsEdge": {
"node": {
"Name": "test",
"Description": "test",
"Errors": [
{
"Message": "Nomination Already Exists"
}
],
"Books": []
}
}
}
}
}
如何通过中继将服务器验证错误消息发送回客户端来编写逻辑?
也试过这个作为我的胖查询
return Relay.QL`
fragment on Nomination_AddPayload {
NominationsEdge {
node{
Errors {
Message
}
}
},
Viewer {
Nominations(first:500){
edges{
node{
id,
Name,
Description
}
}
}
}
}
`;
响应如下:
{,…}
data
:
{Nomination_Add: {clientMutationId: "0", Viewer: {id: "00000000-0000-0000-0000-000000000000"}}}
Nomination_Add
:
{clientMutationId: "0", Viewer: {id: "00000000-0000-0000-0000-000000000000"}}
Viewer
:
{id: "00000000-0000-0000-0000-000000000000"}
id
:
"00000000-0000-0000-0000-000000000000"
clientMutationId
:
"0"
答案 0 :(得分:0)
您没有收到服务器端验证错误消息,因为您没有告诉Relay您想要它们。看看你的GraphiQL变异和你的中继突变的胖查询。您在前者中包含Homestead.yml
,但在后者中不包括。
在您的中继变异(Errors
)胖查询中包含Errors
,如下所示:
Nomination_addMutation
答案 1 :(得分:0)
我可以在mutateAndGetPayload上抛出一个错误:这将作为错误消息发送到突变的onFailure回调,错误信息就是我抛出的内容。
mutateAndGetPayload: ({name, description, books}, context, {rootValue: objectManager}) => {
if(!books){
books = [];
}
return objectManager.add('Nomination', {
name,
description,
books
}, {name: name}).then((nominations) => {
//RT: readability
let nomination = nominations[0];
//RT: if Mongo id is not assigned.
// No records where created.
if(nomination.id == null)
throw nomination.Errors[0].Message;
return ( {nomination}
)});
}
这似乎不是正确的方法。有没有人见过更好的例子?
编辑:清理代码并决定基于这些示例执行此操作。似乎不对。
https://facebook.github.io/relay/docs/api-reference-relay-store.html