普通阵列上的中继突变不起作用

Relay mutation on plain array is not working

我很难弄清楚如何通过中继对普通数组进行突变。

我正在尝试向 post 添加新标签。 在服务器端成功添加后,它不会在客户端更新。

我必须手动重新加载才能看到新标签。 REQUIRED_CHILDRENthis.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,
    }));