Релейная мутация на обычном массиве не работает

Мне трудно понять, как делать мутации в обычном массиве через реле.

Я пытаюсь добавить новый тег к сообщению. Он не обновляется на стороне клиента после успешного добавления на стороне сервера.

Я должен вручную перезагрузить, чтобы увидеть новый тег. Я пробовал и REQUIRED_CHILDREN, и this.props.relay.forceFetch(), но безрезультатно.

Кроме того, попробовал FIELDS_CHANGE для публикации.

Схема GraphQL:

Post {
  id: ID!
  text: String!
  tags: [Tag!]!
}

Tag {
  id: ID!
  name: String!
}

Аддтегтопостмутация:

  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,
      },
    };
  }

person Joon    schedule 13.04.2016    source источник


Ответы (2)


Как уже указывал freiksenet, FIELDS_CHANGE следует использовать в функции getConfigs(). Я взял вашу схему, реализовал типы GraphQL, мутацию на стороне сервера и на стороне клиента, чтобы добавить тег к сообщению. Клиентская сторона успешно обновляется. Я собираюсь просто разработать решение в своем ответе.

Во-первых, проверьте свою мутацию на стороне сервера. В моей реализации используются graphql и graphql-relay и выглядит так, как показано ниже. Обратите внимание, что результатом мутации на стороне сервера является сообщение, к которому был добавлен тег. Этот пост является тем, чей идентификатор был предоставлен в качестве входных данных.

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
      }
    }
  }
}

Я добавил поле posts для всех сообщений в корневой запрос. Используя graphiql, я сначала проверил идентификаторы сообщений и использовал один из них.

При использовании react-relay код мутации на стороне клиента выглядит так, как показано ниже. Ему передается реквизит post, идентификатор которого используется в качестве входной переменной в функции getVariables(). В функции getConfigs() мы указываем, что поле post должно быть обновлено. Связь между полем полезной нагрузки post и переданным свойством 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,
    }));
person Ahmad Ferdous    schedule 14.04.2016

Я думаю, что вы должны просто использовать 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],
      },
    };
  }
person freiksenet    schedule 13.04.2016
comment
Я тоже пробовал FIELDS_CHANGE, но тоже не сработало. - person Joon; 14.04.2016
comment
@Joon Не могли бы вы проверить, какой сервер на самом деле возвращается в Relay из запроса на мутацию (вы можете, например, использовать инструменты React Dev или просто хромировать вкладку «Сеть»)? Видите ли вы сначала оптимистичный ответ «мигание», как будто сначала добавляете тег, а затем удаляете? - person freiksenet; 14.04.2016