突变后,如何跨视图更新受影响的数据?
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
查询容器包装 MyProfile
和 EditMovies
似乎工作正常。在 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
我有 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
查询容器包装 MyProfile
和 EditMovies
似乎工作正常。在 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