React-query: useQuery causes component to render twice

Created on 21 Jul 2020  Â·  6Comments  Â·  Source: tannerlinsley/react-query

Describe the bug
When useQuery is added to a component, that component experiences multiple renders with the same content.

To Reproduce

I am using this component to test:

import React from "react";
import { useQuery } from "react-query";

const myQuery = () =>
  new Promise(resolve => {
    setTimeout(resolve, 500, "SUCCESS");
  });

export const Test = () => {
  const { isLoading, error, data } = useQuery("myquery", myQuery);
  console.log({ isLoading, error, data });
  return <div>Test</div>;
};

Expected behavior

I expected to see in the logs:

{ isLoading: true, error: null, data: undefined }
{ isLoading: false, error: null, data: "SUCCESS" }

Actual Behavior

Instead, what I saw in the logs:

{ isLoading: true, error: null, data: undefined }
{ isLoading: true, error: null, data: undefined }
{ isLoading: false, error: null, data: "SUCCESS" }
{ isLoading: false, error: null, data: "SUCCESS" }

Additional context

It seems like the component is rendering twice as much as it should be.

Most helpful comment

Sorry it took so long to get back. It took me a lot of debugging and trial and error.

Hello @joelnet

that's definitely rerendering 2 times in development, maybe you trying to build to production so the second rendering will be not appears

I was able to confirm that this was not my issue. I could run a production build with NODE_ENV=production webpack --mode production and then serve it with npx serve dist. The issue still persisted.

Hey @joelnet
I was able to replicate this on codesandbox: https://codesandbox.io/s/keen-hellman-xxyto?file=/src/App.js
And after removing strict mode from react, it solves the problem: https://codesandbox.io/s/hungry-lovelace-ig44s?file=/src/App.js

StrictMode renders components twice (on dev but not production) in order to detect any problems with your code and warn you about them (which can be quite useful).

If you have StrictMode enabled in your app but don't remember enabling it, it might be because you used create-react-app or similar to create your app initially, which automatically enables StrictMode by default.

Your codesandbox was very helpful, but this was also not my issue as the setup was done manually (no CRA) and StrictMode was not present.

Eventually, I created a new empty project and useQuery worked correctly. So I started to copy things one by one from the broken project into the working project. Until everything was copied and the project never broke. So now I am really confused.

As a last resort I ran:

rm -rf node_modules package-lock.json
npm install

And it magically started working as expected.

In the end I never found the actual cause. Some outdated dependency? I'll never know.

Thanks to @adibfirman, @PierreAndreis, and @montogeek. I assumed this was expected behavior. So without showing me that it should not behave that way, I would not have spent so much time investigating this.

TL;DR There was a problem with either my node_modules or package-lock.json. I deleted them and reinstalled dependencies.

¯\_(ツ)_/¯

All 6 comments

I converted the code to use this instead:

const everything = useQuery("myquery", myQuery);
console.log(JSON.stringify(everything));

and it seems like there are changes in the return from useQuery.

Most notably is the instances, which is an empty array and then the 2nd render becomes:

  [
      {
        id: 0,
        config: {
          suspense: false,
          enabled: true,
          retry: 3,
          staleTime: 0,
          cacheTime: 300000,
          refetchOnWindowFocus: false,
          refetchInterval: false,
          refetchOnMount: true,
          useErrorBoundary: false
        }
      }
    ]

There are also added props in the 2nd render:

  cancelled: null,
  promise: {}

So it looks like these multiple renders are as designed.

Anyone more familiar have some additional comments on this behavior that could help my understanding?

Hello @joelnet

that's definitely rerendering 2 times in development, maybe you trying to build to production so the second rendering will be not appears

Hey @joelnet
I was able to replicate this on codesandbox: https://codesandbox.io/s/keen-hellman-xxyto?file=/src/App.js
And after removing strict mode from react, it solves the problem: https://codesandbox.io/s/hungry-lovelace-ig44s?file=/src/App.js

StrictMode renders components twice (on dev but not production) in order to detect any problems with your code and warn you about them (which can be quite useful).

If you have StrictMode enabled in your app but don't remember enabling it, it might be because you used create-react-app or similar to create your app initially, which automatically enables StrictMode by default.

This behaviour is documented: https://reactjs.org/docs/strict-mode.html

Note:
This only applies to development mode. Lifecycles will not be double-invoked in production mode.

Sorry it took so long to get back. It took me a lot of debugging and trial and error.

Hello @joelnet

that's definitely rerendering 2 times in development, maybe you trying to build to production so the second rendering will be not appears

I was able to confirm that this was not my issue. I could run a production build with NODE_ENV=production webpack --mode production and then serve it with npx serve dist. The issue still persisted.

Hey @joelnet
I was able to replicate this on codesandbox: https://codesandbox.io/s/keen-hellman-xxyto?file=/src/App.js
And after removing strict mode from react, it solves the problem: https://codesandbox.io/s/hungry-lovelace-ig44s?file=/src/App.js

StrictMode renders components twice (on dev but not production) in order to detect any problems with your code and warn you about them (which can be quite useful).

If you have StrictMode enabled in your app but don't remember enabling it, it might be because you used create-react-app or similar to create your app initially, which automatically enables StrictMode by default.

Your codesandbox was very helpful, but this was also not my issue as the setup was done manually (no CRA) and StrictMode was not present.

Eventually, I created a new empty project and useQuery worked correctly. So I started to copy things one by one from the broken project into the working project. Until everything was copied and the project never broke. So now I am really confused.

As a last resort I ran:

rm -rf node_modules package-lock.json
npm install

And it magically started working as expected.

In the end I never found the actual cause. Some outdated dependency? I'll never know.

Thanks to @adibfirman, @PierreAndreis, and @montogeek. I assumed this was expected behavior. So without showing me that it should not behave that way, I would not have spent so much time investigating this.

TL;DR There was a problem with either my node_modules or package-lock.json. I deleted them and reinstalled dependencies.

¯\_(ツ)_/¯

@joelnet thanks for this issue. The same thing was happening to me - component rendered twice with the same data if useQuery was used.

Don't know what was the reason but

rm -rf node_modules package-lock.json
npm install

helped!!!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

GuillaumeSpera picture GuillaumeSpera  Â·  5Comments

AngusMorton picture AngusMorton  Â·  4Comments

tiagoengel picture tiagoengel  Â·  5Comments

aleksandarcrvc picture aleksandarcrvc  Â·  3Comments

CreativeTechGuy picture CreativeTechGuy  Â·  3Comments