在 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 resetStore 在 Angular 客户端中不起作用