With redux, when the state changes it updates any components props that is connect
ed to the store with mapStateToProps
. However with Apollo when performing a mutation, any component that is using the same data receive the new props.
I understand this is expected behaviour because Apollo doesn't know that the data sets are the same. Here's an example of what I'm getting at:
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})
}
}
The Header
component renders out the username
, where as the Edit component updates the username
. I want to re-render Header
when username
changes. I'm not sure how to do this without polling the query.
Apollo keeps an internal cache of queries and is able to normalize the result sets with dataIdFromObject using the internal cache kept in the redux store.
In order to use the internal cache you must set dataIdFromObject
when initializing your client:
const client = new ApolloClient({
dataIdFromObject: o => o.id
})
Then when performing a mutation, ensure the id
is returned in the return type:
const mutation = gql`mutation updateAccount($username: String!) {
updateAccount(username: $username) {
me {
id
username
}
}
}`
The query should also contain the id:
const query = gql`query { me { id username } }`
Apollo will recognise that the id
is identical between the query and the return type of the mutation and update the query data accordingly.
I'm using Global ID's in my GraphQL API so the id
is always unique across types but if you are using auto-increment ids or they are not unique then you can use __typename
from the object:
const client = new ApolloClient({
dataIdFromObject: o => `${o.__typename}:${o.id},`
})