react-apollo
react-apollo copied to clipboard
Refresh Issue
Hello everyone,
I followed the tutoriel React/Apollo and I faced some refresh issue with this project:
-
First when you log in , the Header seems not rerendered (you don't have the submit button even if you're logged in , see the image below, you can see that you are logged in cause you see the vote below links)
-
Then it seems that the pagination (or the data fetch by the query is not working well, or need to be refetched when page in URL change ?) - in my dataset I have 6 links First you are on the page one, you can see 5 links (normal behavior)
Then you click on the next page on you see a new link (based on the pagination system , normal behavior)
If you hit again previous button, there is on the page only one link (and not the 5 previous one , bug)
So is it a normal case with apollo ? do we need to have a useEffect hook in linklist.js like the code bellow ? The hook useQuery does not rerender the component in such cases ? or is it a problem with the InMemoryCache ? (even in the apollo dev tools extension, the parameters variables for the FETCH Query seems not changing at all)
const history = useHistory();
const isNewPage = history.location.pathname.includes("new");
const pageIndexParams = history.location.pathname.split("/");
const page = parseInt(pageIndexParams[pageIndexParams.length - 1]);
const pageIndex = page ? (page - 1) * LINKS_PER_PAGE : 0;
const { data, loading, error, subscribeToMore, refetch } = useQuery(
FEED_QUERY,
{
variables: getQueryVariables(isNewPage, page),
}
);
useEffect(() => {
console.log("refetch");
refetch();
}, [page]);
I have the same issue...
Same here. It also happens if I go to "/top" from "/new/1" I'll get only 5 links. And if I refresh "/top" I see all the links as expected, and when I switch from "/top" back to "/new/1" it shows all of my links instead of just the 5. So it seems like navigating through the app doesn't refresh the links properly.
I had the same problem while following the tutorial. So I went through the apollo docs and found a solution to share. In conclusion, you can use polling or refetching to solve this problem. It works when useQuery() of LinkList Component is modified as follows.
- in LinkList.js
const { data, loading, error, subscribeToMore, refetch } = useQuery(
FEED_QUERY,
{
variables: getQueryVariables(isNewPage, page),
onCompleted: (data) => { // Added
refetch(); // Added
}, // Added
}
);
or
const { data, loading, error, subscribeToMore } = useQuery(
FEED_QUERY,
{
variables: getQueryVariables(isNewPage, page),
pollInterval: 500, // Added, (not recommended; my opinion)
}
);
The problem of not re-rendering headers when logging in can be solved by using callback.
- in App.js
...
const App = () => {
const [, setIsLogin] = useState(localStorage.getItem(AUTH_TOKEN) !== null);
const handleLogin = () => {
const authToken = localStorage.getItem(AUTH_TOKEN);
setIsLogin(authToken !== null);
};
return (
<div className="center w85">
<Header onLogin={handleLogin} /> // Changed
<div className="ph3 pv1 background-gray">
<Switch>
<Route exact path="/" render={() => <Redirect to="/new/1" />} />
<Route exact path="/create" component={CreateLink} />
<Route
exact
path="/login"
render={() => <Login onLogin={handleLogin} />} // Changed
/>
<Route exact path="/search" component={Search} />
<Route exact path="/top" component={LinkList} />
<Route exact path="/new/:page" component={LinkList} />
</Switch>
</div>
</div>
);
};
- in Login.js
...
const [login] = useMutation(LOGIN_MUTATION, {
variables: {
email: formState.email,
password: formState.password,
},
onCompleted: ({ login }) => {
localStorage.setItem(AUTH_TOKEN, login.token);
history.push("/");
onLogin(); // Added
},
});
const [signup] = useMutation(SIGNUP_MUTATION, {
variables: {
name: formState.name,
email: formState.email,
password: formState.password,
},
onCompleted: ({ signup }) => {
localStorage.setItem(AUTH_TOKEN, signup.token);
history.push("/");
+ onLogin();
},
});
...
- in Header.js
return (
<div className="flex pa1 justify-between nowrap orange">
...
<div className="flex flex-fixed">
{authToken ? (
<div
className="ml1 pointer black"
onClick={() => {
localStorage.removeItem(AUTH_TOKEN);
history.push(`/`);
onLogin(); // Added
}}
>
logout
</div>
) : (
<Link to="/login" className="ml1 no-underline black">
login
</Link>
)}
</div>
</div>
);
};
The reason of such behavior is that useQuery has a default fetch policy cache-first
, which means that it takes the data for the query from cash.
The easy way to fix it is to set fetch policy manually (see Pagination and Cache updates):
const [result] = useQuery({
query: FEED_QUERY,
variables,
requestPolicy: 'cache-and-network' // Added
})
More complicated way will be to define a custom merge function to merge loaded data, but then we should use fetchMore
for pagination, which means we should not follow the whole pagination chapter of the tutorial, which seems wrong.
@paleika Unfortunately your solution doesn't work for me.
InMemoryCache uses id
fields by default to identify results and keep them in cache. But the problem is in feed.id
field, because it's constant (server always sends 'main-feed' value), so InMemoryCache saves all results under same key.
Check out data in apolloClient.cache.data.data
to see what I mean.
To fix the issue we can get rid of feed.id
, since it means nothing for client

I'm somewhat surprised that the folks in charge of howtographql decided that the pagination section of the tutorial was 'done' in its current state. Does everyone that follows the tutorial have a paginated 'new' page that clicking "Previous" on doesn't work properly? It would be really awesome if they would update the documentation so that this part works in an official/best practices. way
I'm somewhat surprised that the folks in charge of howtographql decided that the pagination section of the tutorial was 'done' in its current state. Does everyone that follows the tutorial have a paginated 'new' page that clicking "Previous" on doesn't work properly? It would be really awesome if they would update the documentation so that this part works in an official/best practices. way
This feed is open from January 2021 -> so no hope they will reply and correct it now :'( (cause the whole pagination chapter is incorrect and is not working properly)