apollo-client: Loading stuck always true after sending request when using useQuery hook and React 18 StrictMode

Intended outcome:

The useQuery hook should work with React 18 with StrictMode enabled between multiple component re-renders (Note similarity to #9602) and also update the resulting data and loading state when changing the variables (or other options) passed to the hook.

Actual outcome:

When using the useQuery hook in a component with React StrictMode on, the first time the hook is used (i.e., passing the initial options to the hook) the loading state is properly set to true and then to false after the request has finished loading. However, after changing the variables option passed to the hook, the loading state is set to true, and stays like that forever.

How to reproduce the issue:

Create a simple React app like the one below and keep switching back and forth between the Exchange rates USD and Exchange rates EUR links which changes the variables parameter currency passed to the useQuery hook. You should see that the first time the hook is used with the passed variable (with either USD or EUR as the chosen currency), the loading state is correctly set to false after the request finishes. However, after switching the currency the loading state is stuck as true.

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { Route, BrowserRouter as Router, Routes, Link, useParams } from 'react-router-dom';
import {
  ApolloClient,
  InMemoryCache,
  ApolloProvider,
  useQuery,
  gql
} from "@apollo/client";

const client = new ApolloClient({
  uri: 'https://48p1r2roz4.sse.codesandbox.io',
  cache: new InMemoryCache()
});

const EXCHANGE_RATES = gql`
  query GetExchangeRates($currency: String!) {
    rates(currency: $currency) {
      currency
      rate
    }
  }
`;

function ExchangeRates() {
  const { currency } = useParams();
  const { loading, error, data } = useQuery(EXCHANGE_RATES, {
    variables: { currency },
    fetchPolicy: 'no-cache',
  });

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error :(</p>;

  return data.rates.map(({ currency, rate }) => (
    <div key={currency}>
      <p>
        {currency}: {rate}
      </p>
    </div>
  ));
}

function App() {
  return (
    <div>
      <Router>
        <nav>
          <ul>
            <li>
            <Link to="/">Home</Link>
            </li>
            <li>
            <Link to="/exchangerates/USD">Exchange rates USD</Link>
            </li>
            <li>
            <Link to="/exchangerates/EUR">Exchange rates EUR</Link>
            </li>
          </ul>
        </nav>
        <Routes>
          <Route path="/exchangerates/:currency" element={<ExchangeRates />} />
          <Route path="/" element={<div>Home</div>} />
        </Routes>
      </Router>
    </div>
  );
}

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <ApolloProvider client={client}>
      <App />
    </ApolloProvider>
  </StrictMode>
);

Versions

System: OS: Windows 10 10.0.19044 Binaries: Node: 16.14.2 - ~\AppData\Local\Volta\tools\image\node\16.14.2\node.EXE npm: 8.5.0 - ~\AppData\Local\Volta\tools\image\node\16.14.2\npm.CMD
Browsers: Chrome: 100.0.4896.127 Edge: Spartan (44.19041.1266.0), Chromium (100.0.1185.39) npmPackages: @apollo/client: ^3.6.0 => 3.6.0 graphql: 16.4.0 react: 18.0.0 react-dom: 18.0.0 react-router-dom: 6.3.0

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 9
  • Comments: 16 (3 by maintainers)

Commits related to this issue

Most upvoted comments

I’m still on React 17.0.2 and it also looks to be hanging on the loading state with useQuery and strict mode.

I can confirm I have @viliket’s reproduction running locally and demonstrating the problem. Thanks everyone for raising this issue so quickly after the 3.6 release!

I’m also seeing this with the following versions:

“react”: “17.0.2”, “@apollo/client”: “^3.5.10”

Downgrading to @apollo/client@3.5.10 worked.

@benjamn Thanks, can confirm that the @apollo/client@3.6.1 fixes the issue with StrictMode and works properly on both React 18.0.0 and React 18.0.1. I confirmed this with both the provided example code in this issue as well as an actual app where I first noticed this problem. In addition, with 3.6.1 the problem no longer appears with useLazyQuery where similar problem was noticeable if it was used in a manner where it was always called with useEffect with StrictMode on component re-render (probably because it internally uses useQuery) that had similar problem of loading state getting stuck to true.

Still having this issue, but only when deployed online. It works fine on localhost.

I tried downgrading both @apollo/client and graphql, upgrading @apollo/client to the beta version, using a trigger onCompleted instead of using loading

Any other workaround here?

Thanks to @viliket’s reproduction, I am reasonably confident these issues will be fixed if you run

npm i @apollo/client@next

to install version 3.6.1, which includes #9636. As soon as we get some further confirmation of the fix, we will promote that version to latest on npm.

same here, react 17 and react-native 0.68.1, client @3.6.0, downgrading to 3.5.10 works as expected.