[英]How to handle unresolved props in relay mutations?
我創建了一個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 })
執行時,中繼將user
僅設置了id
身份傳遞到后端,沒有任何其他屬性。 由於輸入變量缺少其他字段,因此不執行該突變。
在調試了突變之后,我看到this.props.user
在除id之外的所有字段上都設置了undefined
。 但是, this._unresolvedProps.user
是正確設置所有字段的user
。
當我更改變異的代碼並將所有this.props
替換為this._unresolvedProps
,所有必要的數據都將傳輸到后端,並且變異得以執行而沒有任何錯誤。 前端緩存似乎也已正確更新(諸如firstName
類的字段在其他組件中已更新)。 但是我不希望這是正確的方法。
我想念什么?
更新
UserDetails
組件加載諸如loginName
類的用戶數據,並提供文本框來更改這些屬性。 相應的中繼容器如下所示:
export default Relay.createContainer(UserDetails, {
fragments: {
user: () => Relay.QL`
fragment on User {
id,
loginName,
firstName,
lastName,
mail,
roles {
id,
name
},
${UserMutation.getFragment("user")}
}
`
}
});
我在文本輸入處理程序中處理文本框更改...
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
傳遞給該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 });
}
});
}
我使用C#后端: graphql-dotnet 。 這是我為突變定義的:
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));
}
}
您的中繼容器是否正確提取User
片段? 我在您的static fragments
定義中看到用戶唯一ID片段是字段,所以我想知道您的父Relay組件是否正在全部獲取它們。
由於您的突變實際上取決於這些字段,因此請將它們添加到fragments
屬性。
class UserMutation extends Relay.Mutation {
public getMutation() { ... }
// getVariables, FatQuery and Configs ...
static fragments = {
user: () => Relay.QL`
fragment on User {
id,
loginName,
firstName,
lastName,
mail
}
`
}
}
然后嘗試將此片段包含在使用您的突變的Relay組件中。 示例React-Relay組件:
import UserMutation from 'mutations/user';
class User extends Component {
commit(e) {
Relay.Store.commitUpdate(
new UserMutation({
user: this.props.user
})
);
}
render() {
return (
<div>Hello</div>
);
}
};
export default Relay.createContainer(User, {
fragments: {
user: () => Relay.QL`
fragment on User {
${UserMutation.getFragment('user')}
}
`,
}
});
使用REQUIRED_CHILDREN並更新組件中的狀態。
您可以使用REQUIRED_CHILDREN而不是使用FIELDS_CHANGE,這將使您可以將返回的已保存對象添加到商店中。 您將要做的是像這樣設置getConfigs:
getConfigs() {
return [{
type: 'REQUIRED_CHILDREN',
children: [
Relay.QL`
fragment on UserPayload {
user {
id
loginName
firstName
lastName
mail
}
}
`
]
}]
}
並更改您的commitUpdate,如下所示:
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配置用於將其他子項附加到突變查詢中。 例如,您可能需要使用它來獲取由該突變創建的新對象上的字段(並且中繼通常不會嘗試獲取該對象,因為該對象以前沒有為該對象獲取任何東西)。
由於REQUIRED_CHILDREN配置而獲取的數據未寫入客戶端存儲,但是您可以在傳遞給commitUpdate()的onSuccess回調中添加處理該數據的代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.