react-apollo
react-apollo copied to clipboard
useQuery returns incorrect results when returning from the cache
I have a list control that uses useQuery to search for items. For simplicity I write useQuery(QUERY, XXX), where XXX is a current parameter of the query.
Component calls useQuery in following order (as I type in the search bar):
useQuery(QUERY, '') // all good all records are returned
useQuery(QUERY, 'f') // records only with 'f' in the name are returned
useQuery(QUERY, '') // ERROR: here I expect again ALL records, but only the 'f' record is shown
How to reproduce the issue:
Reproduction code in the next post.
Here is a gif:
Version
System:
OS: macOS 10.15.1
Binaries:
Node: 12.8.0 - /usr/local/bin/node
Yarn: 1.19.1 - ~/.yarn/bin/yarn
npm: 6.12.0 - /usr/local/bin/npm
Browsers:
Chrome: 78.0.3904.108
Firefox: 70.0.1
Safari: 13.0.3
npmPackages:
@apollo/client: ^3.0.0-beta.14 => 3.0.0-beta.14
@apollo/react-testing: 3 => 3.1.3
npmGlobalPackages:
apollo-fetch: 0.7.0
apollo: 2.21.0
OK, took some time, but I have a complete repro for you. Just run the code below and first type 'f', it will filter the dogs with 'f' in the name. Then delete 'f' and you'll see that nothing will happen as the query returns incorrect data.
Setup
npx create-react-app my-app --typescript
cd my-app
yarn add @apollo/client
yarn add @apollo/react-testing
yarn start
then, replace file App.ts with this file below:
import { MockedProvider } from "@apollo/react-testing";
import React from "react";
import gql from "graphql-tag";
import { useQuery } from "@apollo/client";
// Make sure the query is also exported -- not just the component
export const GET_DOG_QUERY = gql`
query getDog($name: String) {
dogs(name: $name) {
id
name
breed
}
}
`;
export function Dog() {
const [search, setSearch] = React.useState("");
const { loading, error, data } = useQuery(GET_DOG_QUERY, {
variables: { name: search }
});
return (
<>
<label>Search: </label>
<input value={search} onChange={e => setSearch(e.currentTarget.value)} />
{loading && <p>Loading...</p>}
{error && <p>Error!: {JSON.stringify(error)}</p>}
<ul>
{!loading &&
data.dogs.map((d: any) => (
<li key={d.name}>
{d.name} is a {d.breed}
</li>
))}
</ul>
</>
);
}
// The component AND the query need to be exported
const mocks = [
{
request: {
query: GET_DOG_QUERY,
variables: {
name: ""
}
},
result: {
data: {
dogs: [
{ id: "1", name: "Fido", breed: "bulldog" },
{ id: "2", name: "Bucky", breed: "pitbull" }
]
}
}
},
{
request: {
query: GET_DOG_QUERY,
variables: {
name: "b"
}
},
result: {
data: {
dogs: [{ id: "2", name: "Bucky", breed: "pitbull" }]
}
}
},
{
request: {
query: GET_DOG_QUERY,
variables: {
name: "f"
}
},
result: {
data: {
dogs: [{ id: "1", name: "Fido", breed: "bulldog" }]
}
}
}
];
const App: React.FC = () => {
return (
<MockedProvider mocks={mocks} addTypename={false}>
<Dog />
</MockedProvider>
);
};
export default App;
I am facing the exact issue, did you end up finding a solution?
I have also reported it here: https://github.com/apollographql/react-apollo/issues/3742
I am not sure why there is no response from the Apollo team but they must be swamped with preparing 3.0 launch. This is a serious bug IMHO :/
As a temporary workaround you can use network-only
fetchPolicy for queries that are affected by this issue.
Still happening on ^3.0.0-beta.16
Any update on this? Use network-only
for us is not an option
According to apollo-client#5659 this was fixed in 3.0.0-beta.24
For a temporary solution, you can try to set fetchPolicy: 'no-cache'
same issue here, even after migrating to last version or using fetchPolicy: 'no-cache'
Found a workaround by switching to useLazyQuery. I put the search parameter in a useEffect dependency, then the useEffect will execute the query anytime the search parameter changes.
const [getSearchResults, { loading, error, data }] = useLazyQuery(GET_SEARCH_RESULTS, {
variables: {
search: mySearch
}
});
useEffect(() => {
getSearchResults();
}, [mySearch]);
I'm having the same problem when using a Subscription. When changing the query/variables by removing a field, the results don't change. The subscription/query doesn't even decide to fetch again. This is true even when no-cache is set. This fails on react-apollo 3.0.0 and up. The same code works on 2.5.8 and below.
I can provide sample code if needed, but I'm assuming I'm seeing the same bug as already mentioned.
Has anyone had any luck with fixes that would work with a Subscription?
Hi! I had the same problem, was getting the wrong results from cache, adding:
__typename @skip(if: true)
on the query, fixed it.
this article helped: https://kamranicus.com/posts/2018-03-06-graphql-apollo-object-caching