【问题标题】:apollo's useQuery data does not update after client.resetStore()apollo 的 useQuery 数据在 client.resetStore() 之后没有更新
【发布时间】:2021-02-09 15:51:51
【问题描述】:

我遇到了来自@apollo/clientuseQuery 的问题

我有一个Navbar 组件

const Navbar = () => {
  const { loading, data, error } = useQuery(GET_CURRENT_USER);

  console.log('navbar', data)

  return <ReactStuff />
}

我还有一个UserProfile 组件,它允许用户通过按钮注销。当用户按下按钮时,会运行以下代码:

const {
  getCurrentUser,
  changePassword,
  changePasswordData,
  logoutUser,
} = useUsers();

const logout = () => {
  logoutUser();
  localStorage.removeItem("authToken");
  props.history.push("/");
};

useUsers 是一个自定义钩子,其中包含 resetStore 函数:

const useUser = () => {
  const { client, loading, error, data, refetch } = useQuery(GET_CURRENT_USER);
    
  const logoutUser = () => {
    console.log("firing logout user");
    client
      .resetStore()
      .then((data) => {
        console.log("here in reset store success");
      })
      .catch((err) => {
        console.log("here in error");
      }); // causes uncaught error when logging out.
    };
    
  return {
    // other useUser functions
    logoutUser
  }
}

现在我无法弄清楚为什么Navbar 组件在按下logout 时没有得到更新。

我有一个withAuth 高阶组件,它执行完全相同的查询,这绝对没问题。用户被发送到 /login 页面,如果我是 console.log(data),它会更新为未定义 - 正如预期的那样。


import { GET_CURRENT_USER } from "../graphql/queries/user";

/**
 * Using this HOC
 * we can check to see if the user is authed
 */
const withAuth = (Component) => (props) => {
  const history = useHistory();
  const { loading, data, error } = useQuery(GET_CURRENT_USER);

  if (error) console.warn(error);
  if (loading) return null;

  if (data && data.user) {
    return <Component {...props} />;
  }

  if (!data) {
    history.push("/login");
    return "null";
  }

  return null;
};

出于某种原因,Navbar 中的这个 useQuery 出于某种原因保留了这些陈旧的数据,我不知道如何使其正常工作。

更新 1:

我已将logoutUser 函数更改为使用clearStore(),同样的事情发生了,导航栏没有更新,但我被重定向到/login 并且withAuth 按预期工作。

const logoutUser = () => {
  client
    .clearStore()
    .then((data) => console.log(data)) // logs []
    .catch((err) => console.log(err)); // no error because no refetch
  };

【问题讨论】:

  • 您是否通过控制台在导航栏组件内记录用户数据来检查导航栏是否在您注销后重新呈现?

标签: javascript reactjs graphql apollo


【解决方案1】:

您没有等待商店重置,可能重定向和存储清理发生在重置完成之前,请在完成后尝试这样做

const logout = () => {
  logoutUser(() => {
    localStorage.removeItem('authToken');
    props.history.push('/');
  });
};

const logoutUser = onLogout => {
  console.log('firing logout user');
  client
    .resetStore()
    .then(data => {
      onLogout();
    })
    .catch(err => {
      console.log('here in error');
    }); // causes uncaught error when logging out.
};

【讨论】:

  • 不幸的是,这并没有解决我的问题。我删除了props.history.push('/)`,但仍然面临这个问题。这是因为我正在删除 localStorage authToken,然后 client.resetStore() 正在执行所有查询并出错,因为它没有经过身份验证。
  • @KarlTaylor 那么您缺少的是导航栏组件中的错误处理,检查它何时收到身份验证错误,并显示未经身份验证的导航栏版本
  • 这不是我所缺少的。我不需要处理 NavBar 组件中的错误,这个用例根本不应该发生错误 - 用户只需注销,并且需要显示新的导航栏。我在这里找到了答案github.com/apollographql/apollo-client/issues/…
【解决方案2】:

检查:您是否只有一个 ApolloClient 实例?

在某些情况下,如果您在自定义类或文件中配置 ApolloClient,您可以隐式创建多个 apolloClient 实例,例如通过“import”语句。在这种情况下,您只清除您所做的缓存之一。

【讨论】:

    猜你喜欢
    • 2020-06-04
    • 2021-10-31
    • 1970-01-01
    • 2020-02-01
    • 2020-08-05
    • 1970-01-01
    • 2018-11-20
    • 1970-01-01
    • 2021-05-31
    相关资源
    最近更新 更多