tronx.dev
tronx.dev

Reputation: 138

How to prevent re-rendering with useSubscription()?

Many of you might have heard of GraphQL. It provides QUERY and MUTATION. Also it supports SUBSCRIPTION as 100% replacement of web socket. I'm a big fan of GraphQL and hooks. Today I faced an issue with useSubscription which is a hook version of SUBSCRIPTION. When this subscription is fired, a React component is re-rendered. I'm not sure why it causes re-rendering.

import React from 'react'
import { useSubscription } from 'react-apollo'

const Dashboard = () => {
  ...
  useSubscription(query, {
    onSubscriptionData: data => {
      ...
    }
  })

  render (
    <>
      Dashboard
    </>
  )
}

Actually useSubscription's API doc doesn't say anything about this re-rendering now. It would be really appreciated if you provide me a good solution to preventing the re-rendering.

Thanks!

Upvotes: 1

Views: 2149

Answers (3)

Richard
Richard

Reputation: 1046

With later versions of Apollo client, the easiest way to achieve this is to use the ignoreResults option.

import { useSubscription } from '@apollo/client'

const Dashboard = () => {
  ...
  useSubscription(query, {
    onSubscriptionData: data => {
      ...
    },
    ignoreResults: true,
  })

  render (
    <>
      Dashboard
    </>
  )
}

Upvotes: 0

Ihor Voit
Ihor Voit

Reputation: 41

Just put your subscription in separate component as this guy did, and return null, now your root component won't rerender

function Subscription () {
  const onSubscriptionData = React.useCallback(
    handleSubscription,  // your handler function
    [])

  useSubscription(CHAT_MESSAGE_SUBSCRIPTION, {
    shouldResubscribe: true,
    onSubscriptionData
  })

  return null
}

// then use this component
<Subscription />

Upvotes: 4

Michael
Michael

Reputation: 1872

In my experience, there is no way to prevent re-render when receiving new data in onSubscriptionData. If your global data is used for calculations, you should use useMemo for you global variable. On the other hand, you should consider do you need put your variable in onSubscriptionData? Are there other ways? Did you use useSubscription in right component? If your have to do that, you have to accept extra rendering.
Hopefully, my answer is helpful for your situation.

Upvotes: 0

Related Questions