Skip to content
This repository has been archived by the owner on Apr 13, 2023. It is now read-only.

useSubscription triggers unnecessary rerenders #3549

Open
borremosch opened this issue Oct 2, 2019 · 6 comments
Open

useSubscription triggers unnecessary rerenders #3549

borremosch opened this issue Oct 2, 2019 · 6 comments

Comments

@borremosch
Copy link

I am using useSubscription in one of my components. I do not use any of the return values, because I am using a complicated protocol in my subscription, and I do not want to act on every message I receive. Instead, I am using the onSubscriptionData callback function. I was surprised to see that even though I only update state on some of the received messages, my component is rerendering continuously. It seems that using useSubscription will trigger a re-render every time subscription data is received, even if it is discarded.

It would be very useful to have a version of useSubscription that does not trigger a re-render whenever data is received, and instead let the user decide when to make state changes in onSubscriptionData. For now, I have had to put my subscription in a sub-component, just to make the superfluous re-rendering computationally cheaper.

I am using @apollo/react-hooks version 3.1.2.

  System:
    OS: Linux 5.0 Ubuntu 19.04 (Disco Dingo)
  Binaries:
    Node: 10.16.0 - /usr/bin/node
    Yarn: 1.19.0 - /usr/bin/yarn
    npm: 6.10.0 - ~/cubonacci/services/ui/node_modules/.bin/npm
  Browsers:
    Chrome: 77.0.3865.90
    Firefox: 69.0.1
  npmPackages:
    @apollo/react-components: ^3.1.2 => 3.1.2 
    @apollo/react-hoc: ^3.1.2 => 3.1.2 
    @apollo/react-hooks: ^3.1.2 => 3.1.2 
    apollo-cache-inmemory: ^1.6.3 => 1.6.3 
    apollo-client: ^2.6.4 => 2.6.4 
    apollo-link-http: ^1.5.16 => 1.5.16 
    apollo-link-ws: ^1.0.19 => 1.0.19 
@safead
Copy link

safead commented Jan 8, 2020

Same issue here

@filipmares
Copy link

filipmares commented Mar 12, 2020

My team is also seeing this issue. Causing way too many re-renders. We're going to try the same approach as mentioned by @borremosch.

@0xdevalias
Copy link

0xdevalias commented Apr 8, 2020

EDIT: re-reading your original issue, I think my below is actually irrelevant, and the real reason is just that the setResult is always going to be called, which will cause the re-renders: https://github.com/apollographql/apollo-client/blob/master/src/react/hooks/useSubscription.ts#L19-L23


@borremosch @filipmares I'm not 100% if this will solve your issues, but if you are defining your onSubscriptionData handler inline, every time the hook is run/processed, you're actually passing an entirely new anonymous function to the hook.

The general way to resolve this is to use React's useCallback handler:


Digging deeper to confirm the theory, I found the related code at the following:

 public setOptions(
    newOptions: CommonOptions<TOptions>,
    storePrevious: boolean = false
  ) {
    if (storePrevious && !equal(this.options, newOptions)) {
      this.previousOptions = this.options;
    }
    this.options = newOptions;
  }

In particular, the !equal(this.options, newOptions), which uses:

/**
 * Performs a deep equality check on two JavaScript values, tolerating cycles.
 */
export function equal(a: any, b: any): boolean {
  // ..snip..
}

@icodeforlove
Copy link

I am seeing this happening when enabling reconnect.

A rerender is triggered every XX seconds (depends on timeout/keep-alive).

Any idea on how to prevent this rerender?

@tronxdev
Copy link

Today I faced the same issue with useSubscription. Whenever a subscription is fired, a React component is re-rendered. It isn't mentioned in useSubscription's API doc. What can I do to prevent the re-rendering?

@0xdevalias , could you elaborate your solution for me? It sounds good, but I'm not sure I follow.
Thanks in advance!

@tronxdev
Copy link

My team is also seeing this issue. Causing way too many re-renders. We're going to try the same approach as mentioned by @borremosch.

Hi @filipmares , did you resolve this issue? If yes, could you tell me how to?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants