dataIdFromObject 不更新的 Apollo 规范化
Apollo Normalization with dataIdFromObject not updating
我在发送删除突变后无法让 React+Apollo 更新商店。我正在使用内置了 apollo+react 的 reactQL 样板和一个 express graphQL 服务器(我没有安装 apollo 服务器——我只是使用参考 express-graphQL 包)。我的数据存储在 mongoDB 中,带有 _id
,但客户端的实际数据使用 id
作为 id。
apollo客户端是这样定义的:
new ApolloClient(
Object.assign(
{
reduxRootSelector: state => state.apollo,
dataIdFromObject: o => o.id
},
opt
)
);
我有一个父组件使用
从 'src/graphql/queries/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
}
}
Apollo 的dataIdFromObject
用于更新缓存中已有的对象。因此,如果您有一个记录和一个 ID,并且您根据同一个 ID 更改了其他数据,则监听商店的 React 组件可以重新呈现。
由于您的 deleteCourse
变异似乎 return 相同的 ID,它仍然存在于缓存中。您的商店不知道它需要删除 - 它只是用返回的任何数据更新缓存。由于此突变可能 return 是相同的 ID,因此没有任何迹象表明应将其删除。
相反,您需要指定一个 update function(link 转到官方 Apollo 文档)以明确删除底层存储数据。
在我的新 ReactQL user auth example, I do the same thing (see the pertinent LOC here) 中 'manually' 在用户登录后更新商店。
由于组件最初侦听 'blank' 用户,我不能依赖 dataObjectFromId
来使缓存无效,因为我开始时没有用户,因此没有 ID。所以我手动显式覆盖存储状态,这会触发任何监听组件的重新渲染。
我解释的概念是 YouTube 视频中上述用户身份验证的上下文 - 这是相关的部分:https://youtu.be/s1p4R4rzWUs?t=21m12s
我在发送删除突变后无法让 React+Apollo 更新商店。我正在使用内置了 apollo+react 的 reactQL 样板和一个 express graphQL 服务器(我没有安装 apollo 服务器——我只是使用参考 express-graphQL 包)。我的数据存储在 mongoDB 中,带有 _id
,但客户端的实际数据使用 id
作为 id。
apollo客户端是这样定义的:
new ApolloClient(
Object.assign(
{
reduxRootSelector: state => state.apollo,
dataIdFromObject: o => o.id
},
opt
)
);
我有一个父组件使用 从 'src/graphql/queries/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
}
}
Apollo 的dataIdFromObject
用于更新缓存中已有的对象。因此,如果您有一个记录和一个 ID,并且您根据同一个 ID 更改了其他数据,则监听商店的 React 组件可以重新呈现。
由于您的 deleteCourse
变异似乎 return 相同的 ID,它仍然存在于缓存中。您的商店不知道它需要删除 - 它只是用返回的任何数据更新缓存。由于此突变可能 return 是相同的 ID,因此没有任何迹象表明应将其删除。
相反,您需要指定一个 update function(link 转到官方 Apollo 文档)以明确删除底层存储数据。
在我的新 ReactQL user auth example, I do the same thing (see the pertinent LOC here) 中 'manually' 在用户登录后更新商店。
由于组件最初侦听 'blank' 用户,我不能依赖 dataObjectFromId
来使缓存无效,因为我开始时没有用户,因此没有 ID。所以我手动显式覆盖存储状态,这会触发任何监听组件的重新渲染。
我解释的概念是 YouTube 视频中上述用户身份验证的上下文 - 这是相关的部分:https://youtu.be/s1p4R4rzWUs?t=21m12s