在 Apollo 客户端上注销

Posted

技术标签:

【中文标题】在 Apollo 客户端上注销【英文标题】:Logout on Apollo-Client 【发布时间】:2020-08-06 20:57:06 【问题描述】:

我正在使用带有 Expo 的 react-native 开发一个应用程序,该应用程序使用 Apollo 与 GraphQL 后端交互。

Front 和 Back 之间的授权是通过标头上的 JWT 令牌完成的,并且工作正常。在后端有一个中间件来检查令牌是否存在并且是否有效:

如果查询已打开,它只会检索信息。 如果查询已获得授权并且用户已通过身份验证,它将检索信息。 如果查询已获得授权,但用户未登录(或使用无效令牌),则会引发错误。

后台

export const isAuth: MiddlewareFn<MyContext> = ( context , next) => 
    const  authorization  = context.req.headers;

    if (!authorization) 
        throw new Error("Not authenticated. ");
    
[...]


@Query(() => User)
@UseMiddleware(isAuth)
async Me(
    @Ctx()  payload : MyContext,
) 
    return UserModel.findById(payload!.userId);

我获取查询的方式是通过以下组件:

前端

const Me: React.FC<any> = (props) => 
    const 
        data, loading, error,
     = useMeQuery();

    if (loading) 
        return (<Text>Loading ... String(props.test)</Text>);
    
    if (error) 
        return (<Text> error.message  String(props.test)</Text>);
    
    return (
        <Text>Hello  String(data?.Me?.email)  </Text>
    );
;

作为useMeQuery(); 一个由@graphql-codegen/cli 生成的钩子函数。

export function useMeQuery(baseOptions?: ApolloReactHooks.QueryHookOptions<MeQuery, MeQueryVariables>) 
        return ApolloReactHooks.useQuery<MeQuery, MeQueryVariables>(MeDocument, baseOptions);

到目前为止,它工作正常。

现在,我正在尝试在前端实现注销功能,以便用户在注销时可以继续以匿名用户身份导航。

我刚刚创建了一个按钮,该按钮调用一个清除存储令牌的函数(它正在工作),因此下一个调用未经过身份验证并引发错误。我遇到的问题是 apollo-client 正在使用缓存来重新呈现查询,因此现在匿名用户能够看到 old-LogedIn 用户信息。

为了注销,我尝试了几种清除缓存的方法,都没有成功:

clearTokens(); // Clear tokens from asyncStorage. Working fine.

// Tying to clear cache:
client.clearStore(); // Not working, still getting the stored value on cache when refreshing the component.
client.cache.reset(); // Not working, still getting the stored value on cache when refreshing the component.
client.resetStore(); // Not working, it tries to call the query again, it throws an error (because it is not authenticated) and doesn't clear the cache.

使用apollo-client 时退出的最佳方式是什么?

PD:如果另一个用户登录,我调用client.resetStore(); 并且所有查询都重新获取,工作正常。问题只是从 login 传递到 anonymous。

【问题讨论】:

【参考方案1】:

我找到了解决方案。

关于我读过的关于这个问题但使用 React 的其他主题。他们谈论导航到另一个页面,但是,在 react-native 上,它不起作用,因为当导航到另一个页面时,最后一页保持打开状态。解决方案是使用props.navigation.replace("Logout"); 导航到另一个页面。

退出页面只需做任何事情,使用client.clearStore(); 清除缓存,然后使用navigation.replace 自动导航到主页面。

【讨论】:

【参考方案2】:

对于 apollo v3,我必须同时做这两件事:

client.clearStore();
client.cache.gc();

【讨论】:

以上是关于在 Apollo 客户端上注销的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Apollo 中关闭 GraphQL 订阅的套接字连接

Apollo 客户端不显示错误消息

如果令牌过期,如何在 apollo 客户端中重定向或导航

Apollo resetStore 在 Angular 客户端中不起作用

登录状态不会在 React、Apollo Client 2、Graphcool 中被动更新

如何在本地网络上部署带有 apollo 客户端和 apollo-server 后端的 React 应用程序