I am playing around the code: https://codesandbox.io/s/restless-framework-uldf4q?file=/src/App.js
import React, { Fragment } from "react";
import { gql } from "apollo-boost";
import { useQuery } from "@apollo/react-hooks";
const GET_DOG_PHOTO = gql`
query Dog($breed: String!) {
dog(breed: $breed) {
id
displayImage
}
}
`;
const breed = "dingo";
const App = () => {
const [count, setCount] = React.useState(0);
const { loading, error, data, startPolling, stopPolling } = useQuery(
GET_DOG_PHOTO,
{
variables: { breed },
onCompleted: () => {
setCount((count) => count + 1);
}
}
);
if (loading) {
return <h2>loading</h2>;
}
if (error) {
return <h2>Whoops</h2>;
}
return (
<div>
<h1> {count}</h1>
<Fragment>
<img
alt="Cute Doggo"
src={data.dog.displayImage}
style={{ height: 500, width: 500 }}
/>
<button onClick={() =>startPolling(500)}>Start</button>
<button onClick={stopPolling}>Stop</button>
</Fragment>
</div>
);
};
export default App;
In my code, I setCount to count+1 using React.useState in the onCompleted callback? why it just stop counting when polling?
so what is the mechanism here?
3 Answers
I can also observe that the onCompleted
callback is not invoked as expected in the reproducer you provide.
In your CodeSandbox, you are using a 3-year-old deprecated version of the useQuery
hook. You could migrate to the latest @apollo/client
package, which will solve the issue.
See this migrated CodeSandbox: https://codesandbox.io/s/apolllo-on-completed-n9wzge
You can also use notifyOnNetworkStatusChange
option as true
. It will change the loading state as well every time.
Call api as
const { loading, error, data, startPolling, stopPolling } = useQuery(
GET_DOG_PHOTO,
{
variables: { breed },
notifyOnNetworkStatusChange: true,
onCompleted: () => {
setCount((count) => count + 1);
}
}
);
As of Apollo 3.8+, onCompleted
only gets called when notifyOnNetworkStatusChange
is set to true
. However, this is not ideal because it calls onCompleted
several times per second, regardless of the pollInterval
that you set. You’re better off placing the contents of onCompleted
in a useEffect()
, with data
as a dependency.
const { loading, error, data, startPolling, stopPolling } = useQuery(
GET_DOG_PHOTO,
{
variables: { breed }
}
);
useEffect(() => {
setCount((count) => count + 1);
}, [data]);