I have the following GraphQL operation that works:
GraphQL Mutation:
mutation CreateUserMutation ($input: CreateUserInput!) {
createUser(input: $input) {
clientMutationId
userEdge {
node {
email
username
}
},
validationErrors {
id
email
}
}
}
GraphQL mutation response:
{
"data": {
"createUser": {
"clientMutationId": "112",
"userEdge": {
"node": {
"email": "[email protected]",
"username": "soosap112"
}
},
"validationErrors": {
"id": "create-user-validation-errors",
"email": [
"Email looks not so good."
]
}
}
}
}
So far so good, my GraphQL response's validationErrors is an object of key-value pairs, where the value is always an array of input validation error messages from the server w/ respect to a particular input field (i.e. {'email': ['email is taken', 'email is on blacklist']}).
Next step (and this is where I need help) - how to consume that data in the Relay client store? In other words, what to do to have the validationErrors available in my component as 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',
},
},
];
}
}
Here is my attempt: First of all I am able to consume user edges into my Relay client store by using the getConfigs RANGE_ADD. Since my validationErrors object does not implement the connection model, the FIELDS_CHANGE seemed to be the only reasonable type in my case. I am trying to mock the dataID that Relay seems to require to populate the client store using 'create-user-validation-errors' as a unique id.
Here is a snippet from my React component to make the example complete.
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,
})
);
};
How do I consume a non-connection model based piece of information from a GraphQL response in a React component using Relay? Minimum working example would be awesome.
Do you know of a better way of doing server-side input validation using GraphQL and Relay?