react-query 遇到 401 时尝试刷新令牌并使查询无效

Posted

技术标签:

【中文标题】react-query 遇到 401 时尝试刷新令牌并使查询无效【英文标题】:Try refresh token and invalidate query when react-query encounters 401 【发布时间】:2021-05-20 12:55:15 【问题描述】:

我想围绕 react-query 的 useQuery 钩子创建一个包装器钩子,以便捕获 401 错误,尝试刷新访问令牌,如果成功刷新 - 使原始查询无效。

我正在尝试做的完整示例在这里:https://codesandbox.io/s/agitated-booth-hbe12?file=/src/App.js

function useMyQUery() 
  const queryClient = useQueryClient();
  const  tryRefreshToken  = useSession();

  const query = useQuery(...arguments);

  if (query.isError && query.error?.status === 401) 
    tryRefreshToken().then((tokenRefreshSucccessful) =>
      queryClient.invalidateQueries("todos")
    );
   else 
    return query;
  

  return ;

在我上面链接的示例中,我能够捕捉到错误,触发函数tryRefetchToken,但useSession 钩子内的函数似乎在设置后不会拾取令牌。

【问题讨论】:

【参考方案1】:

我认为你不能直接在渲染函数中触发像 tryRefreshToken()queryClient.invalidateQueries 这样的副作用。尝试将这些副作用放入useQueryonError 回调或useEffect。比如:

function useMyQUery() 
  const queryClient = useQueryClient()
  const  tryRefreshToken  = useSession()

  return useQuery(key, fn, 
    onError: (error) => 
      if (error.status === 401) 
        tryRefreshToken().then((tokenRefreshSucccessful) =>
          queryClient.invalidateQueries("todos")
        )
      
    
  )

【讨论】:

感谢您让我走上正确的道路,但是onError 不会阻止错误暴露给消费者,但有效的是retry 选项,它接受回调函数(retryCount, error) => ... ,它按预期工作并且不会将错误暴露给消费者,除非您从该回调中返回 false。现在我遇到的最后一个问题是在 useSession 上下文中设置的 queryFn 应该从该上下文中读取状态值 token,但它永远不会获得更新的值,只是初始值。 如果你想完全隐藏错误,我会直接在queryFn进行刷新 我想让它与查询功能分离,我不希望它完全消失,第一次吞下 401。

以上是关于react-query 遇到 401 时尝试刷新令牌并使查询无效的主要内容,如果未能解决你的问题,请参考以下文章

使用 React/Typescript 的 React-query 数据的 SetState

使用 axios 拦截器时,API 调用循环出现 401 错误

尝试在http拦截器中捕获401,刷新我的会话并重试原始请求

使用 MSW 测试 React-query,并将数据传递给子组件

Angular 4 和 OAuth - 拦截 401 响应,刷新访问令牌并重试请求

React Native 中的 Auth0 刷新令牌失败并显示 401