普通阵列上的中继突变不起作用
Relay mutation on plain array is not working
我很难弄清楚如何通过中继对普通数组进行突变。
我正在尝试向 post 添加新标签。
在服务器端成功添加后,它不会在客户端更新。
我必须手动重新加载才能看到新标签。
REQUIRED_CHILDREN
和 this.props.relay.forceFetch()
我都试过了,但是没用。
此外,尝试 FIELDS_CHANGE
post。
GraphQL 架构:
Post {
id: ID!
text: String!
tags: [Tag!]!
}
Tag {
id: ID!
name: String!
}
AddTagToPostMutation:
static fragments = {
post: () => Relay.QL`
fragment on Post {
id
tags
}
`,
}
getMutation() {
return Relay.QL`mutation { addTagToPost }`;
}
getVariables() {
return {
name: this.props.tag.name,
};
}
getFatQuery() {
return Relay.QL`
fragment on AddTagToPostMutationPayload {
tag {
id
name
}
post {
id
tags
}
}
`;
}
getConfigs() {
return [{
type: 'REQUIRED_CHILDREN',
children: [Relay.QL`
fragment on AddTagToPostMutationPayload {
tag {
id
name
}
post {
id
tags
}
}
`],
}];
}
getOptimisticResponse() {
return {
tag: {
name: this.props.tag.name,
},
post: {
id: this.props.post.id,
},
};
}
我认为你应该在这种情况下使用 FIELDS_CHANGE。
getConfigs() {
return [{
type: 'FIELDS_CHANGE',
fieldIDs: {post: this.props.post.id},
}];
}
getOptimisticResponse() {
return {
post: {
id: this.props.post.id,
tags: [...this.props.post.tags, this.props.tag],
},
};
}
正如 freiksenet 已经指出的,FIELDS_CHANGE
应该在 getConfigs()
函数中使用。我采用了您的架构,实施了 GraphQL 类型、服务器端和客户端变更,以将标签添加到 post。客户端更新成功。我将在我的回答中详细说明解决方案。
首先,检查您的服务器端突变。我的实现使用 graphql and graphql-relay 库,如下所示。请注意,服务器端突变的输出是添加了标签的 post。此 post 是其 ID 作为输入提供的那个。
const AddTagToPostMutation = mutationWithClientMutationId({
name: 'AddTagToPost',
inputFields: {
postId: { type: new GraphQLNonNull(GraphQLID) },
name: { type: new GraphQLNonNull(GraphQLString) },
},
outputFields: {
post: {
type: PostType,
resolve: ({id}) => getPost(id),
},
},
mutateAndGetPayload: ({postId, name}) => {
const id = fromGlobalId(postId).id;
addTagToPost(id, name);
return {id};
},
});
使用graphiql,你可以测试你的变异:
mutation {
addTagToPost(input:{
postId: "UG9zdDpwb3N0Mg=="
name:"a new tag name"
clientMutationId:"123244"}) {
post {
id
text
tags {
id
name
}
}
}
}
我为所有 post 添加了一个字段 posts
到根查询。使用 graphiql,我首先检查了 post 个 ID,并在上面使用了一个。
使用react-relay,客户端变异代码如下所示。它传递了一个道具 post
,其 ID 在 getVariables()
函数中用作输入变量。在 getConfigs()
函数中,我们指定必须更新 post
字段。 payload 字段 post
和传递的 prop post
之间的关联是使用 FIELDS_CHANGE
突变类型建立的。
export default class AddTagToPostMutation extends Relay.Mutation {
getMutation() {
return Relay.QL`mutation{addTagToPost}`;
}
getVariables() {
return {
postId: this.props.post.id,
name: this.props.name,
};
}
getFatQuery() {
return Relay.QL`
fragment on AddTagToPostPayload {
post {
id,
tags {
id,
name,
}
}
}
`;
}
getConfigs() {
return [{
type: 'FIELDS_CHANGE',
fieldIDs: {
post: this.props.post.id,
},
}];
}
static fragments = {
post: () => Relay.QL`
fragment on Post {
id,
}
`,
};
}
客户端变更是这样调用的:
Relay.Store.commitUpdate(new AddTagToPostMutation({
post: postToModify,
name: tagName,
}));
我很难弄清楚如何通过中继对普通数组进行突变。
我正在尝试向 post 添加新标签。 在服务器端成功添加后,它不会在客户端更新。
我必须手动重新加载才能看到新标签。
REQUIRED_CHILDREN
和 this.props.relay.forceFetch()
我都试过了,但是没用。
此外,尝试 FIELDS_CHANGE
post。
GraphQL 架构:
Post {
id: ID!
text: String!
tags: [Tag!]!
}
Tag {
id: ID!
name: String!
}
AddTagToPostMutation:
static fragments = {
post: () => Relay.QL`
fragment on Post {
id
tags
}
`,
}
getMutation() {
return Relay.QL`mutation { addTagToPost }`;
}
getVariables() {
return {
name: this.props.tag.name,
};
}
getFatQuery() {
return Relay.QL`
fragment on AddTagToPostMutationPayload {
tag {
id
name
}
post {
id
tags
}
}
`;
}
getConfigs() {
return [{
type: 'REQUIRED_CHILDREN',
children: [Relay.QL`
fragment on AddTagToPostMutationPayload {
tag {
id
name
}
post {
id
tags
}
}
`],
}];
}
getOptimisticResponse() {
return {
tag: {
name: this.props.tag.name,
},
post: {
id: this.props.post.id,
},
};
}
我认为你应该在这种情况下使用 FIELDS_CHANGE。
getConfigs() {
return [{
type: 'FIELDS_CHANGE',
fieldIDs: {post: this.props.post.id},
}];
}
getOptimisticResponse() {
return {
post: {
id: this.props.post.id,
tags: [...this.props.post.tags, this.props.tag],
},
};
}
正如 freiksenet 已经指出的,FIELDS_CHANGE
应该在 getConfigs()
函数中使用。我采用了您的架构,实施了 GraphQL 类型、服务器端和客户端变更,以将标签添加到 post。客户端更新成功。我将在我的回答中详细说明解决方案。
首先,检查您的服务器端突变。我的实现使用 graphql and graphql-relay 库,如下所示。请注意,服务器端突变的输出是添加了标签的 post。此 post 是其 ID 作为输入提供的那个。
const AddTagToPostMutation = mutationWithClientMutationId({
name: 'AddTagToPost',
inputFields: {
postId: { type: new GraphQLNonNull(GraphQLID) },
name: { type: new GraphQLNonNull(GraphQLString) },
},
outputFields: {
post: {
type: PostType,
resolve: ({id}) => getPost(id),
},
},
mutateAndGetPayload: ({postId, name}) => {
const id = fromGlobalId(postId).id;
addTagToPost(id, name);
return {id};
},
});
使用graphiql,你可以测试你的变异:
mutation {
addTagToPost(input:{
postId: "UG9zdDpwb3N0Mg=="
name:"a new tag name"
clientMutationId:"123244"}) {
post {
id
text
tags {
id
name
}
}
}
}
我为所有 post 添加了一个字段 posts
到根查询。使用 graphiql,我首先检查了 post 个 ID,并在上面使用了一个。
使用react-relay,客户端变异代码如下所示。它传递了一个道具 post
,其 ID 在 getVariables()
函数中用作输入变量。在 getConfigs()
函数中,我们指定必须更新 post
字段。 payload 字段 post
和传递的 prop post
之间的关联是使用 FIELDS_CHANGE
突变类型建立的。
export default class AddTagToPostMutation extends Relay.Mutation {
getMutation() {
return Relay.QL`mutation{addTagToPost}`;
}
getVariables() {
return {
postId: this.props.post.id,
name: this.props.name,
};
}
getFatQuery() {
return Relay.QL`
fragment on AddTagToPostPayload {
post {
id,
tags {
id,
name,
}
}
}
`;
}
getConfigs() {
return [{
type: 'FIELDS_CHANGE',
fieldIDs: {
post: this.props.post.id,
},
}];
}
static fragments = {
post: () => Relay.QL`
fragment on Post {
id,
}
`,
};
}
客户端变更是这样调用的:
Relay.Store.commitUpdate(new AddTagToPostMutation({
post: postToModify,
name: tagName,
}));