突变后,如何跨视图更新受影响的数据?

After a mutation, how do I update the affected data across views?

我有 getMovies 查询和 addMovie 突变工作。但是,当 addMovie 发生时,我想知道如何最好地更新 "Edit Movies" 和 "My Profile" 中的电影列表以反映更改。我只需要一个 general/high-level 概述,或者如果简单的话,甚至只是一个概念的名称,关于如何实现这一点。

我最初的想法是将所有电影都放在我的 Redux 商店中。变异完成后,它应该 return 新添加的电影,我可以将其连接到我商店的电影。

在 "Add Movie" 之后,它会弹出到 "Edit Movies" 屏幕,您应该可以在其中看到新添加的电影,然后如果您返回到 "My Profile",它'我也会去的。

有没有比将其全部保存在我自己的 Redux 商店中更好的方法呢?是否有任何我不知道的 Apollo 魔法可以为我处理此更新?


编辑:我发现了updateQueries的想法:http://dev.apollodata.com/react/cache-updates.html#updateQueries我想这就是我想要的(如果不是,请告诉我正确的做法)。这似乎比使用我自己的 Redux 存储的传统方式更好。

// this represents the 3rd screen in my picture
const AddMovieWithData = compose(
  graphql(searchMovies, {
    props: ({ mutate }) => ({
      search: (query) => mutate({ variables: { query } }),
    }),
  }),
  graphql(addMovie, {
    props: ({ mutate }) => ({
      addMovie: (user_id, movieId) => mutate({
        variables: { user_id, movieId },
        updateQueries: {
          getMovies: (prev, { mutationResult }) => {
            // my mutation returns just the newly added movie
            const newMovie = mutationResult.data.addMovie;

            return update(prev, {
              getMovies: {
                $unshift: [newMovie],
              },
            });
          },
        },
      }),
    }),
  })
)(AddMovie);

addMovie 突变之后,这正确地更新了 "My Profile" 中的视图,因为它使用了 getMovies 查询(哇哦)!然后我将这些电影作为道具传递给 "Edit Movies",那么我如何在那里更新它呢?我应该让他们都使用 getMovies 查询吗?有没有办法将 getMovies 的新结果从存储中提取出来,这样我就可以在 "Edit Movies" 上重复使用它而无需再次进行查询?


EDIT2: 使用 getMovies 查询容器包装 MyProfileEditMovies 似乎工作正常。在 addMovie 之后,由于 getMovies 上的 updateQueries,它在两个地方都更新了。它也很快。我认为它正在被缓存?

一切正常,所以我想这只是一个问题:这是最好的方法吗?

标题问题的答案是

使用 updateQueries 来“通知”驱动其他视图的查询数据已更改(正如您发现的那样)。

这个话题在 react-apollo 松弛频道中得到持续讨论,这个答案是我所知道的共识:没有明显的替代方案。

请注意,您可以更新多个查询(这就是名称为复数且参数是一个 object 的原因,其中包含与所有需要更新的查询的名称相匹配的键)。

正如您可能猜到的那样,这 "pattern" 确实意味着您在设计和使用查询时需要小心,以便在设计变更时使生活变得轻松和可维护。更常见的查询意味着您在突变 updateQueries 操作中错过一个的机会更少。

Apollo 客户端仅在更新突变时更新存储。因此,当您使用创建或删除突变时,您需要告诉 Apollo Client 如何更新。我原以为商店会自动更新,但它没有…

我在完成你的突变后就找到了 resetStore 的解决方法。 您在进行突变后立即重置商店。然后当你需要查询时,store 是空的,所以 apollo 重新获取新数据。

代码如下:

import { withApollo } from 'react-apollo'

...

  deleteCar = async id => {
    await this.props.deleteCar({
      variables: { where: {
        id: id
      } },
    })
    this.props.client.resetStore().then(data=> {
      this.props.history.push('/cars')
    })
  }


...


export default compose(
  graphql(POST_QUERY, {
    name: 'carQuery',
    options: props => ({
      fetchPolicy: 'network-only',
      variables: {
        where: {
          id: props.match.params.id,
        }
      },
    }),
  }),
  graphql(DELETE_MUTATION, {
    name: 'deleteCar',
  }),
  withRouter,
  withApollo
)(DetailPage)

完整代码在这里:https://github.com/alan345/naperg 破解前的错误 resetStore