Ich habe eine Relay.Mutation
, dass Updates auf User
Objekte ausgelöst werden soll:Wie mit ungelösten Requisiten in Relay-Mutationen umgehen?
class UserMutation extends Relay.Mutation {
public getMutation() {
return Relay.QL`mutation {saveUser}`;
}
public getVariables() {
return {
id: this.props.user.id,
loginName: this.props.user.loginName,
firstName: this.props.user.firstName,
lastName: this.props.user.lastName,
mail: this.props.user.mail
}
}
public getFatQuery() {
return Relay.QL`
fragment on UserPayload {
user {
id,
loginName,
firstName,
lastName,
mail
}
}
`;
}
public getConfigs() {
return [{
type: "FIELDS_CHANGE",
fieldIDs: {
user: this.props.user.id
}
}];
}
static fragments = {
user:() => Relay.QL`
fragment on User {
id,
// I initially had only id here
loginName,
firstName,
lastName,
mail
}
`
}
}
ich diese Mutation in meiner Komponente UserDetails
wie diese bin mit:
// I initially passed this.props.user to the mutation
this.props.relay.commitUpdate(new UserMutation({ user: this.state.user })
Bei der Ausführung, Relais eine user
zu den Pässen Backend mit nur id
gesetzt, ohne irgendeine andere Eigenschaft. Die Mutation wird nicht ausgeführt, da die anderen Felder in der Eingabevariablen fehlen.
Nach dem Debuggen in die Mutation, sah ich, dass this.props.user
undefined
auf allen Feldern gesetzt hat, aber ID. this._unresolvedProps.user
ist jedoch ein user
mit allen Feldern richtig eingestellt.
Wenn ich den Code der Mutation ändern und alle this.props
durch this._unresolvedProps
ersetzen, werden alle notwendigen Daten an das Backend übertragen und die Mutation wird ohne Fehler ausgeführt. Der Frontend-Cache scheint ebenfalls korrekt aktualisiert zu sein (Felder wie firstName
werden in anderen Komponenten aktualisiert). Aber ich erwarte nicht, dass dies der richtige Weg ist.
Was vermisse ich?
UPDATE
Die UserDetails
Komponente lädt Benutzer Daten wie loginName
und liefert Textfelder, diese Eigenschaften zu ändern. Die entsprechenden Relais Container sehen wie folgt aus:
export default Relay.createContainer(UserDetails, {
fragments: {
user:() => Relay.QL`
fragment on User {
id,
loginName,
firstName,
lastName,
mail,
roles {
id,
name
},
${UserMutation.getFragment("user")}
}
`
}
});
I Textfeld Änderungen in einem Texteingabehandler ...
public handleTextInput(fieldName: string, event: any) {
let user = this.state.user;
switch (fieldName) {
case "loginName": {
user.loginName = event.target.value;
break;
}
case "firstName": {
user.firstName = event.target.value;
break;
}
case "lastName": {
user.lastName = event.target.value;
break;
}
case "mail": {
user.mail = event.target.value;
break;
}
}
this.setState({ user: user });
}
... behandeln und in einem einreichen Handler einreichen bilden, wo ich jetzt passieren this.state.user
die Mutation:
public handleSubmit(e: any) {
e.preventDefault();
this.props.relay.commitUpdate(new UserMutation({ user: this.state.user }), {
onSuccess: (response: any) => {
this.setState({ user: response.saveUser.user });
}
});
}
ich benutze einen C# Backend: graphql-dotnet. Das ist, was ich für die Mutation definiert:
public class ApplicationSchema : Schema
{
public ApplicationSchema()
{
this.Query = new ApplicationQuery();
this.Mutation = new ApplicationMutation();
}
}
public class ApplicationMutation : ObjectGraphType
{
public ApplicationMutation()
{
this.Name = "Mutation";
// save a user
this.Field<UserPayloadType>(
"saveUser",
arguments: new QueryArguments(
new QueryArgument<NonNullGraphType<UserInputType>>
{
Name = "input",
Description = "the user that should be saved"
}),
resolve: context =>
{
var userInput = context.Argument<UserInput>("input");
var clientMutationId = userInput.ClientMutationId;
var user = MemoryRepository.UpdateUser(new User()
{
Id = userInput.Id,
LoginName = userInput.LoginName,
FirstName = userInput.FirstName,
LastName = userInput.LastName,
Mail = userInput.Mail
});
return new UserPayload()
{
ClientMutationId = clientMutationId,
User = user
};
});
}
}
public class UserInputType : InputObjectGraphType
{
public UserInputType()
{
this.Name = "UserInput";
this.Field<NonNullGraphType<StringGraphType>>("id", "The id of the user.");
this.Field<NonNullGraphType<StringGraphType>>("loginName", "The login name of the user.");
this.Field<NonNullGraphType<StringGraphType>>("firstName", "The first name of the user.");
this.Field<NonNullGraphType<StringGraphType>>("lastName", "The last name of the user.");
this.Field<NonNullGraphType<StringGraphType>>("mail", "The mail adress of the user.");
this.Field<NonNullGraphType<StringGraphType>>("clientMutationId", "react-relay property.");
}
}
public class UserPayloadType : ObjectGraphType
{
public UserPayloadType()
{
this.Name = "UserPayload";
this.Field<NonNullGraphType<UserType>>("user", "The user.");
this.Field<NonNullGraphType<StringGraphType>>("clientMutationId", "react-relay property.");
}
}
public class UserType : ObjectGraphType
{
public UserType()
{
this.Name = "User";
this.Field<NonNullGraphType<StringGraphType>>("id", "The id of the user.");
this.Field<NonNullGraphType<StringGraphType>>("loginName", "The login name of the user.");
this.Field<NonNullGraphType<StringGraphType>>("firstName", "The first name of the user.");
this.Field<NonNullGraphType<StringGraphType>>("lastName", "The last name of the user.");
this.Field<NonNullGraphType<StringGraphType>>("mail", "The mail adress of the user.");
Field<ListGraphType<RoleType>>("roles", resolve: context => MemoryRepository.GetRolesOfUser(context.Source as DomainModel.Models.User));
}
}
Können Sie bitte Ihre serverseitige GraphQL Mutation zeigen 'saveUser'? Problem könnte mit 'saveUser' sein. –
Fügen Sie auch das Feld "Fragmente" Ihres Relay-Containers hinzu. –
Ich habe gerade die erforderlichen Codefragmente hinzugefügt. Vielen Dank. –