【问题标题】:useLazyQuery not being called after onClickonClick 后未调用 useLazyQuery
【发布时间】:2020-07-20 03:36:06
【问题描述】:

我正在尝试使用来自用户的 GraphQL API 数据的查询来检查我的用户 isLoggedIn 是否已登录,否则它应该返回未定义或某些错误。

问题是我有一个名为 removeSession 的函数,当用户单击注销按钮时,它会从我的 localStorage 中删除令牌。问题从现在开始,我意识到我的令牌已从 localStorage 中清除,但之后未触发 userLAzyQuery。因此,为了检查我开始手动删除 de 令牌,在 onClick 之后我调用了sendQuery()

为了强制检查,我在查询后创建了onCompletedonError 回调,你猜怎么着?也没有被调用。

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;

查询/索引.ts

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

我正在使用 next.js、apollo 3、react16.12 仅供参考

在我的网络标签中没有任何 XHR 活动的信号

更新 1:我在我的lazyQuery 中添加了fetchPolicy,我的请求出现在 chromedev 工具中,但状态已取消

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

【问题讨论】:

  • await sendQuery(); 或将Router.push('/'); 移动到onCompleted
  • 它没有调用 onCompleted... 并且 await 没有工作 =(
  • 禁用/注释掉Router.push ?
  • @DanielRearden 仍然无法正常工作,我很确定这不是路由器的问题,因为当我单击时,我可以调用我的 removeSession 函数,但语句 sendQuery() 没有被调用!跨度>

标签: typescript graphql react-hooks apollo


【解决方案1】:

当组件安装在此处时,您已经在运行相同的查询:

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

这意味着,默认情况下,相同查询的后续提取将从缓存中完成。这就是您在“网络”选项卡中看不到任何内容的原因。

为了强制服务器完成请求,我们需要将获取策略更改为network-only

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

我希望onCompleted 无论查询如何完成都会被执行,但我无法确定这是预期行为还是错误。

【讨论】:

  • 我还在学习阿波罗,几周前就开始了,但我认为有必要进行相同的查询。第一个查询是当用户在其本地存储中有令牌时,只有当用户单击注销按钮时才会触发 useLazy。
  • 现在我可以看到我的请求,但是我应该是 POST 的 REQUEST 标头没有定义,我的请求被取消了。我从未见过没有请求方法的请求。
  • 不幸的是,与使用 useMutation 不同,sendQuery 返回 undefined 而不是 Promise。这意味着在调用Router.push 之前,您不能等待查询完成。所以查询被启动,然后你的组件被卸载,导致查询被取消。
  • 有一个未解决的问题here 来更改 API 来解决这个问题。同样的问题包括几个你可以使用的解决方法。
  • 不幸的是仍然是一个问题,useLazyQuery 没有返回承诺。因此,我通过检查 localStorage 值来解决问题,这不是最好的方法,而是耐心。
猜你喜欢
  • 2021-02-06
  • 2020-05-31
  • 1970-01-01
  • 2021-03-13
  • 2021-05-07
  • 1970-01-01
  • 2020-02-04
  • 2020-02-27
  • 1970-01-01
相关资源
最近更新 更多