如何在使用 Apollo 执行突变后更新单独的组件道具

How to update a separate components props after performing a mutation with Apollo

使用 redux,当状态改变时,它会更新 connect 使用 mapStateToProps 到商店的任何组件属性。但是,使用 Apollo 执行突变时,任何使用相同数据的组件都会收到新的道具。

我知道这是预期的行为,因为 Apollo 不知道数据集是相同的。这是我得到的示例:

const query = gql`query { me { username } }`

@graphql(query)
class Header extends React.Component {
  render () {
    return <h1>{this.props.data.me.username}</h1>
  }
}

const mutation = gql`mutation updateAccount($username: String!) {
  updateAccount(username: $username) {
    me {
      username
    }
  }
}`
@graphql(mutation)
class Edit extends React.Component {
  render () {
    # ...
  }
  onSubmit(e) {
    e.preventDefault()
    this.props.mutate({variables: {username: this.state.username})
  }
}

Header 组件呈现 username,而编辑组件更新 username。我想在 username 更改时重新渲染 Header。我不确定如何在不轮询查询的情况下执行此操作。

Apollo 保留查询的内部缓存,并且能够使用保存在 redux 存储中的内部缓存通过 dataIdFromObject 规范化结果集。

为了使用内部缓存,您必须在初始化客户端时设置 dataIdFromObject

const client = new ApolloClient({
  dataIdFromObject: o => o.id
})

然后在执行突变时,确保 id 在 return 类型中被 returned:

const mutation = gql`mutation updateAccount($username: String!) {
  updateAccount(username: $username) {
    me {
      id
      username
    }
  }
}`

查询还应包含 id:

const query = gql`query { me { id username } }`

Apollo 将识别 id 查询与 return 类型的突变相同,并相应地更新查询数据。

我在我的 GraphQL API 中使用全局 ID,因此 id 在不同类型中始终是唯一的,但如果您使用的是自动递增 ID 或者它们不是唯一的,那么您可以使用 __typename 来自对象:

const client = new ApolloClient({
  dataIdFromObject: o => `${o.__typename}:${o.id},`
})