I need some help to figure out what is a general approach on subscriptions and real-time updating. I have a React Native app and using Apollo and Graphcool service as a backend.
There are a couple scenarios where user looking at the app receives a push notification that something has changed. Naturally, the screen data should get updated as well. Subscriptions are an obvious candidate for that job and I got it working essentially.
I have a subscription like this which works just fine on its own (used to position player avatars on google map).
subscription PlayerMap($gameId: ID) {
Game(filter: { mutation_in: [CREATED, UPDATED], node: { id: $gameId } }) {
node {
players {
id
character {
id
name
}
user {
id
latitude
longitude
}
}
}
}
}
Then there is a different app screen executing a mutation createPlayer
along with refetchQueries
from Apollo (for simplicity) which runs this query to update stuff.
query GameCharacters($gameId: ID!) {
Game(id: $gameId) {
players {
id
character {
id
name
}
}
}
}
Now when this completes, the subscription query (that is still active on another screen) also gets updated but for some reason whole Game
node is missing in data
object.
For handling subscriptions, I have a component like this.
class Subscriber extends Component<void, Props, void> {
componentDidMount() {
this.subscribe()
}
componentWillReceiveProps({ data, shouldResubscribe }) {
if (this.unsubscribe) {
if (shouldResubscribe && shouldResubscribe(data, this.props.data) !== true) {
return
}
this.unsubscribe()
}
this.subscribe()
}
subscribe() {
const { data, query, variables } = this.props
this.unsubscribe = data.subscribeToMore({
document: query,
variables,
})
}
unsubscribe: ?Function = null
render() {
return this.props.children(this.props.data)
}
}
I can then use it simply like this with render prop pattern.
const OrgMapScreen = ({ gameId, data: initialData }: Props) => (
<Subscriber
data={initialData}
query={OrgMapSubscription}
variables={{ gameId }}
shouldResubscribe={(nextData, prevData) => nextData.Game !== prevData.Game}
>
{({ Game }) => {
const markers = Game.players.map(makePlayerMarker)
return <MapScreen mapProps={{ markers }} />
}}
</Subscriber>
)
I am rather confused why is that happening. Is there some recommended way how to handle stuff like that? Perhaps instead of refetchQueries
I should set up another subscription for GameCharacters
too?