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
- Pin Apollo Client to 3.5.10 https://github.com/apollographql/apollo-client/issues/9632 — committed to blamattina/githelper by blamattina 2 years ago
I’m still on React
17.0.2
and it also looks to be hanging on the loading state withuseQuery
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 withuseLazyQuery
where similar problem was noticeable if it was used in a manner where it was always called withuseEffect
with StrictMode on component re-render (probably because it internally usesuseQuery
) 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 usingloading
…Any other workaround here?
Thanks to @viliket’s reproduction, I am reasonably confident these issues will be fixed if you run
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.