'useLazyQuery not being called after onClick

I'm trying to check if my user isLoggedIn with a query from GraphQL API data from the user if it's loggedin if not it's supposed to return undefined or some error.

The question is I have a func called removeSession that deletes from my localStorage the token when users click in the logout button. The problem starts now, I've realized that my token was being cleared from localStorage but the userLAzyQuery wasn't get triggered after. So to inspect I started to delete de token manually and after the onClick I invoked the sendQuery()

To force my inspection I created onCompleted and onError callback after the query, and guess what? not being called either.

header.js

import { Fragment, useEffect } from 'react';
import Link from 'next/link';
import { isAuthenticatedQuery } from '../queries';
import { useQuery, useLazyQuery } from '@apollo/react-hooks';
import Router from 'next/router';

function isActive(pathname) {
  return typeof document !== 'undefined' && document.location.pathname === pathname;
}

const Header = () => {
  const { loading, data: dataAuth, error } = useQuery(isAuthenticatedQuery);

  const [sendQuery, { data: dataAuthLazy, error: errorsLazy }] = useLazyQuery(isAuthenticatedQuery, {
    onCompleted(data) {
      console.log('invoked onCompleted', data);
    },
    onError(err) {
      console.log('onerror', err);
    },
  });

  function removeSession() {
    localStorage.removeItem('token');
    sendQuery();
    console.log('inside removeSession');
    Router.push('/');
  }

  return (
    <nav>
      <div className="left">
        <Link href="/">
          <a data-active={isActive('/')}>Blog</a>
        </Link>
        <Link href="/drafts">
          <a data-active={isActive('/drafts')}>Drafts</a>
        </Link>
      </div>
      <div className="right">
        {!!dataAuth || !!dataAuthLazy ? (
          <Fragment>
            <Link href="/create">
              <a data-active={isActive('/create')}>+ Create draft</a>
            </Link>
            <Link href="/login" >
              <a onClick={() => sendQuery()}>Logout</a>
            </Link>
          </Fragment>
        ) : (
          <Fragment>
            <Link href="/signup">
              <a data-active={isActive('/signup')}>Signup</a>
            </Link>
            <Link href="/login">
              <a data-active={isActive('/login')}>Login</a>
            </Link>
          </Fragment>
        )}
      </div>
      <style jsx>{`
        nav {
          display: flex;
          padding: 2rem;
          align-items: center;
        }

        .bold {
          font-weight: bold;
        }

        a {
          text-decoration: none;
          color: gray;
          font-weight: regular;
          display: inline-block;
        }

        .left a[data-active='true'] {
          color: #000;
          font-weight: bold;
        }

        a + a {
          margin-left: 1rem;
        }

        .right {
          margin-left: auto;
        }

        .right a {
          padding: 0.5rem 1rem;
          border-radius: 5px;
          background: hsla(0, 89%, 63%, 0.79);
          color: white;
          font-weight: 500;
        }

        .right a:hover {
          background: hsl(0, 72%, 54%);
        }
      `}</style>
    </nav>
  );
};

export default Header;

queries/index.ts

export const isAuthenticatedQuery = gql`
  query isAuthenticatedQuery {
    me {
      id
      name
      email
    }
  }
`;

I'm using next.js, apollo 3, react16.12 FYI

In my network tabs no signal of some XHR activity

Update 1: I added fetchPolicy in my lazyQuery and my request appeared in chromedev tools but with status canceled

  const [sendQuery, { data: dataAuthLazy, error: errorsLazy }] = useLazyQuery(isAuthenticatedQuery, {
    fetchPolicy: 'no-cache',
    onCompleted(data) {
      console.log('invoked onCompleted', data);
      Router.push('/');
    },
    onError(err) {
      console.log('onerror', err);
    },
  });


Solution 1:[1]

You're already running the same query when the component mounts here:

const { loading, data: dataAuth, error } = useQuery(isAuthenticatedQuery)

That means, by default, subsequent fetches of the same query will be fulfilled from the cache. This is why you don't see anything in the Network tab.

In order to force the request to be fulfilled by the server, we need to change the fetch policy to something like network-only:

const [sendQuery, { data: dataAuthLazy, error: errorsLazy }] = useLazyQuery(isAuthenticatedQuery, {
  fetchPolicy: 'network-only',
})

I would expect onCompleted to be executed regardless of how the query was fulfilled, but I can't speak to whether that is intended behavior or a bug.

Solution 2:[2]

I came to this SO page looking for solution to a very close problem. For me, after the first failure, the onError function wasn't being called for the subsequent error calls.

Adding notifyOnNetworkStatusChange: true worked well for me.

Code Snippet:

     getAccountsQuery,
            {
              fetchPolicy: "no-cache",
              onCompleted: (data) => {
              /// 
              },
              notifyOnNetworkStatusChange: true, // did the work
              onError: (error) => {
                setAccountsApiError(error);
              },
            }
          );

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Daniel Rearden
Solution 2 gursahib.singh.sahni