Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/375.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何处理中继突变中未解决的道具?_Javascript_Reactjs_Graphql_Relay - Fatal编程技术网

Javascript 如何处理中继突变中未解决的道具?

Javascript 如何处理中继突变中未解决的道具?,javascript,reactjs,graphql,relay,Javascript,Reactjs,Graphql,Relay,我创建了一个Relay.Mutation,它应该会触发User对象的更新: class UserMutation extends Relay.Mutation { public getMutation() { return Relay.QL`mutation {saveUser}`; } public getVariables() { return { id: this.props.user.id,

我创建了一个
Relay.Mutation
,它应该会触发
User
对象的更新:

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
            }
        `
    }
}
我在我的组件
UserDetails
中使用了这种变异,如下所示:

// I initially passed this.props.user to the mutation
this.props.relay.commitUpdate(new UserMutation({ user: this.state.user })
export default Relay.createContainer(UserDetails, {
    fragments: {
        user: () => Relay.QL`
            fragment on User {
                id,
                loginName,
                firstName,
                lastName,
                mail,
                roles {
                    id,
                    name
                },
                ${UserMutation.getFragment("user")}
            }
        `
    }
});
getConfigs() {
  return [{
    type: 'REQUIRED_CHILDREN',
      children: [
        Relay.QL`
          fragment on UserPayload {
            user {
              id
              loginName
              firstName
              lastName
              mail
            }
          }
        `
      ]
  }]
}
this.props.relay.commitUpdate(
  new UserMutation({user: this.props.user}),
  {
    onSuccess: response => this.setState({
      user: response.user,
    }),
    onError: err => console.log(err)
  }
);
执行时,中继将一个
用户
传递到后端,只设置了
id
,没有任何其他属性。由于输入变量缺少其他字段,因此不会执行变异

在调试到变异后,我看到
this.props.user
在除id之外的所有字段上都设置了
undefined
。但是,
this.\u unsolvedprops.user
是一个
用户,所有字段都设置正确

当我更改变异的代码并将所有
this.props
替换为
this.\u unsolvedprops
时,所有必要的数据都会传输到后端,变异执行时不会出现任何错误。前端缓存似乎也已正确更新(类似于
firstName
的字段在其他组件中也已更新)。但我不认为这是正确的方式

我错过了什么

更新

UserDetails
组件加载用户数据,如
loginName
,并提供文本框来更改这些属性。相应的中继容器如下所示:

// I initially passed this.props.user to the mutation
this.props.relay.commitUpdate(new UserMutation({ user: this.state.user })
export default Relay.createContainer(UserDetails, {
    fragments: {
        user: () => Relay.QL`
            fragment on User {
                id,
                loginName,
                firstName,
                lastName,
                mail,
                roles {
                    id,
                    name
                },
                ${UserMutation.getFragment("user")}
            }
        `
    }
});
getConfigs() {
  return [{
    type: 'REQUIRED_CHILDREN',
      children: [
        Relay.QL`
          fragment on UserPayload {
            user {
              id
              loginName
              firstName
              lastName
              mail
            }
          }
        `
      ]
  }]
}
this.props.relay.commitUpdate(
  new UserMutation({user: this.props.user}),
  {
    onSuccess: response => this.setState({
      user: response.user,
    }),
    onError: err => console.log(err)
  }
);
我在文本输入处理程序中处理文本框更改

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 });
}
…并在提交处理程序中进行表单提交,现在我将
this.state.user
传递给:

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 });
        }
    });
}
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));
    }
}
我使用C#后端:。这就是我对突变的定义:

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 });
        }
    });
}
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));
    }
}
公共类应用程序模式:模式
{
公共应用程序模式()
{
this.Query=newapplicationquery();
this.Mutation=新应用程序Mutation();
}
}
公共类应用程序置换:ObjectGraphType
{
公共应用程序置换()
{
this.Name=“Mutation”;
//保存用户
这是我的地盘(
“保存用户”,
参数:新的QueryArguments(
新质询
{
Name=“输入”,
Description=“应保存的用户”
}),
解析:上下文=>
{
var userInput=context.Argument(“输入”);
var clientMutationId=userInput.clientMutationId;
var user=MemoryRepository.UpdateUser(新用户()
{
Id=userInput.Id,
LoginName=userInput.LoginName,
FirstName=userInput.FirstName,
LastName=userInput.LastName,
Mail=userInput.Mail
});
返回新的UserPayload()
{
ClientMutationId=ClientMutationId,
用户=用户
};
});
}
}
公共类UserInputType:InputObjectGraphType
{
公共用户输入类型()
{
this.Name=“UserInput”;
这个字段(“id”,“用户的id”);
这个.Field(“loginName”,“用户的登录名”);
字段(“firstName”,“用户的名字”);
此.Field(“lastName”,“用户的姓氏”);
此.Field(“邮件”,“用户的邮件地址”);
这个.Field(“clientMutationId”,“react relay property.”);
}
}
公共类UserPayloadType:ObjectGraphType
{
公共用户PayloadType()
{
this.Name=“UserPayload”;
此字段(“用户”、“用户”);
这个.Field(“clientMutationId”,“react relay property.”);
}
}
公共类UserType:ObjectGraphType
{
公共用户类型()
{
this.Name=“User”;
这个字段(“id”,“用户的id”);
这个.Field(“loginName”,“用户的登录名”);
字段(“firstName”,“用户的名字”);
此.Field(“lastName”,“用户的姓氏”);
此.Field(“邮件”,“用户的邮件地址”);
字段(“角色”,resolve:context=>MemoryRepository.GetRolesOfUser(context.Source作为DomainModel.Models.User));
}
}

使用必需的子项并更新组件中的状态

您可以使用必需的子项来将返回的保存对象添加到存储中,而不是使用字段\u CHANGE。您要做的是如下设置GetConfig:

// I initially passed this.props.user to the mutation
this.props.relay.commitUpdate(new UserMutation({ user: this.state.user })
export default Relay.createContainer(UserDetails, {
    fragments: {
        user: () => Relay.QL`
            fragment on User {
                id,
                loginName,
                firstName,
                lastName,
                mail,
                roles {
                    id,
                    name
                },
                ${UserMutation.getFragment("user")}
            }
        `
    }
});
getConfigs() {
  return [{
    type: 'REQUIRED_CHILDREN',
      children: [
        Relay.QL`
          fragment on UserPayload {
            user {
              id
              loginName
              firstName
              lastName
              mail
            }
          }
        `
      ]
  }]
}
this.props.relay.commitUpdate(
  new UserMutation({user: this.props.user}),
  {
    onSuccess: response => this.setState({
      user: response.user,
    }),
    onError: err => console.log(err)
  }
);
在更改您的提交日期时,如下所示:

// I initially passed this.props.user to the mutation
this.props.relay.commitUpdate(new UserMutation({ user: this.state.user })
export default Relay.createContainer(UserDetails, {
    fragments: {
        user: () => Relay.QL`
            fragment on User {
                id,
                loginName,
                firstName,
                lastName,
                mail,
                roles {
                    id,
                    name
                },
                ${UserMutation.getFragment("user")}
            }
        `
    }
});
getConfigs() {
  return [{
    type: 'REQUIRED_CHILDREN',
      children: [
        Relay.QL`
          fragment on UserPayload {
            user {
              id
              loginName
              firstName
              lastName
              mail
            }
          }
        `
      ]
  }]
}
this.props.relay.commitUpdate(
  new UserMutation({user: this.props.user}),
  {
    onSuccess: response => this.setState({
      user: response.user,
    }),
    onError: err => console.log(err)
  }
);
如您所见,onSuccess回调允许您调用actionCreator并将新用户置于应用程序的状态。这将使用应用程序中使用的任何状态管理来完成。在这种情况下,它只是setState

REQUIRED_CHILDREN config用于将其他子项附加到变异查询。例如,您可能需要使用它来获取由变异创建的新对象上的字段(该中继通常不会尝试获取,因为它以前没有为该对象获取任何内容)

由于必需的_CHILDREN配置而获取的数据不会写入客户端存储,但您可以在传递到commitUpdate()的onSuccess回调中添加处理该数据的代码


使用必需的子项并更新组件中的状态

您可以使用必需的子项来将返回的保存对象添加到存储中,而不是使用字段\u CHANGE。您要做的是如下设置GetConfig:

// I initially passed this.props.user to the mutation
this.props.relay.commitUpdate(new UserMutation({ user: this.state.user })
export default Relay.createContainer(UserDetails, {
    fragments: {
        user: () => Relay.QL`
            fragment on User {
                id,
                loginName,
                firstName,
                lastName,
                mail,
                roles {
                    id,
                    name
                },
                ${UserMutation.getFragment("user")}
            }
        `
    }
});
getConfigs() {
  return [{
    type: 'REQUIRED_CHILDREN',
      children: [
        Relay.QL`
          fragment on UserPayload {
            user {
              id
              loginName
              firstName
              lastName
              mail
            }
          }
        `
      ]
  }]
}
this.props.relay.commitUpdate(
  new UserMutation({user: this.props.user}),
  {
    onSuccess: response => this.setState({
      user: response.user,
    }),
    onError: err => console.log(err)
  }
);
在更改您的提交日期时,如下所示:

// I initially passed this.props.user to the mutation
this.props.relay.commitUpdate(new UserMutation({ user: this.state.user })
export default Relay.createContainer(UserDetails, {
    fragments: {
        user: () => Relay.QL`
            fragment on User {
                id,
                loginName,
                firstName,
                lastName,
                mail,
                roles {
                    id,
                    name
                },
                ${UserMutation.getFragment("user")}
            }
        `
    }
});
getConfigs() {
  return [{
    type: 'REQUIRED_CHILDREN',
      children: [
        Relay.QL`
          fragment on UserPayload {
            user {
              id
              loginName
              firstName
              lastName
              mail
            }
          }
        `
      ]
  }]
}
this.props.relay.commitUpdate(
  new UserMutation({user: this.props.user}),
  {
    onSuccess: response => this.setState({
      user: response.user,
    }),
    onError: err => console.log(err)
  }
);
如您所见,onSuccess回调允许您调用actionCreator并将新用户置于应用程序的状态。这将使用应用程序中使用的任何状态管理来完成。在这种情况下,它只是setState

REQUIRED_CHILDREN config用于将其他子项附加到变异查询。例如,你可能需要使用这个