Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refresh Issue #117

Open
Minifish57 opened this issue Jan 20, 2021 · 7 comments
Open

Refresh Issue #117

Minifish57 opened this issue Jan 20, 2021 · 7 comments

Comments

@Minifish57
Copy link

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)
    Capture d’écran 2021-01-20 à 07 31 01

  • 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)
    Capture d’écran 2021-01-20 à 07 32 28
    Then you click on the next page on you see a new link (based on the pagination system , normal behavior)
    Capture d’écran 2021-01-20 à 07 32 39
    If you hit again previous button, there is on the page only one link (and not the 5 previous one , bug)
    Capture d’écran 2021-01-20 à 07 32 45

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]);
@Waterwolf312
Copy link

I have the same issue...

@FelixPriori
Copy link

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.

@dinobei
Copy link

dinobei commented Mar 8, 2021

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>
  );
};

@paleika
Copy link

paleika commented Mar 10, 2021

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.

@alxmiron
Copy link

@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

Screenshot 2021-03-23 at 00 12 40

@cjsilva-umich
Copy link

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

@Minifish57
Copy link
Author

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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants