Аполлон Нормализация с dataIdFromObject не обновляется

У меня проблемы с получением React+Apollo для обновления магазина после отправки мутации удаления. Я использую стандартную панель ReQL, в которой есть встроенный Apollo+ React и сервер Express GraphQL (я не устанавливал сервер Apollo - я просто использую справочный пакет Express-GraphQL). Мои данные хранятся в mongoDB с _id, но фактические данные на стороне клиента используют id как идентификатор

Клиент Apollo определяется следующим образом:

new ApolloClient(
    Object.assign(
      {
        reduxRootSelector: state => state.apollo,
        dataIdFromObject: o => o.id
      },
      opt
    )
  );

У меня есть родительский компонент, который использует импортные курсы из 'src/graphql/questions/courses.gql

@graphql(courses)
export default class CoursesPage extends Component {
  constructor(props){
    super(props)
    this.handleDelete = this.handleDelete.bind(this);
  }

  handleDelete(event) {
    this.props.mutate({ variables: {id: selectedId}}
              .catch(err => console.log(err))
  }

  render() {
    return (
      { this.props.data.courses.map(course =>
         <CourseDelete selectedId={course.id} key={course.id} />
        })
      }
    )
  }

}

и дочерний компонент, который выглядит как:

import deleteCoursefrom 'src/graphql/mutations/deleteCourse.gql

@graphql(deleteCourse)
export default class CourseDelete extends Component {
  constructor(props){
    super(props)
    this.handleDelete = this.handleDelete.bind(this);
  }

  handleDelete(event) {
    this.props.mutate({ variables: {id: this.props.selectedId}}
              .catch(err => console.log(err))
  }

  render() {
    return (
      <button onClick={this.handleDelete}>Button</button>
    )
  }

}

где deleteCourse.gql:

mutation deleteCourse($id: String!) {
  deleteCourse(id: $id) {
    id
  }
}

и мой оригинальный запрос находится в courses.gql:

query courses {
  courses {
    id
  }
}

1 ответ

Решение

Аполлона dataIdFromObject используется для обновления объектов уже в кеше. Поэтому, если у вас есть запись и идентификатор, и вы меняете другие фрагменты данных на этот же идентификатор, компоненты React, прослушивающие хранилище, могут выполнить повторную визуализацию.

Так как ваш deleteCourse мутация, похоже, возвращает тот же идентификатор, он все еще существует в кэше. Ваш магазин не знает, что он нуждается в удалении - он просто обновляет кеш, возвращая любые данные. Поскольку эта мутация, вероятно, возвращает тот же идентификатор, нет ничего, что бы указывало на то, что это следует удалить.

Вместо этого вам нужно указать функцию обновления (ссылка идет на официальные документы Apollo), чтобы явно удалить данные основного хранилища.

В моем новом примере аутентификации пользователя ReactQL я делаю то же самое ( см. Соответствующий LOC здесь), чтобы "вручную" обновить хранилище после входа пользователя.

Поскольку компоненты изначально слушают "пустого" пользователя, я не могу положиться на dataObjectFromId аннулировать кеш, так как я начинаю без пользователей и, следовательно, без идентификаторов. Поэтому я явно перезаписываю состояние хранилища вручную, что вызывает повторный рендеринг любых слушающих компонентов.

Я объясняю, что концепция - это контекст вышеупомянутой аутентификации пользователя в видео на YouTube - это актуальная часть: https://youtu.be/s1p4R4rzWUs?t=21m12s

Другие вопросы по тегам