【问题标题】:Apollo Graphql when refreshing token doesn't update useQuery刷新令牌时 Apollo Graphql 不更新 useQuery
【发布时间】:2021-10-31 00:01:51
【问题描述】:

我面临下一个问题: 我有一个用于获取 usersData 的 useQuery 钩子

GET_USER_INFO 使用查询

const { data:dataGetUserInfo, loading:loadingQuery, error:errorQuery,refetch  } = useQuery(GET_USER_INFO, {variables: {
            getUserInfoInfoId: userId
        }});

我想在访问令牌过期时刷新访问和刷新令牌。为此,我在 apollo-client.ts 中完成了 errorLink,它在需要时调用了刷新函数,然后调用了我的 GET_USER_INFO useQuery

apollo-client.ts

const getNewToken =  () => {
    let refreshToken

        refreshToken = localStorage.getItem("REFRESH");

    return client.mutate({
        mutation: REFRESH_TOKEN,
        variables:{
            refreshTokenRefreshToken : refreshToken,
        }
    })
        .then((res) => {
            localStorage.clear();
            const { accessToken,refreshToken } = res.data.refreshToken;
            localStorage.setItem('REFRESH',refreshToken)
            localStorage.setItem('AUTHORIZATION',accessToken)
            return res.data;
        }).catch((err)=>{
            console.log(err)
            
        })

};



const errorLink = onError(
    ({ graphQLErrors, networkError, operation, forward }) => {
        if (graphQLErrors) {
            for (let err of graphQLErrors) {

                switch (err.extensions?.code) {
                    
                    case "UNAUTHENTICATED" :
                        console.log('aa')
                        return fromPromise(
                            getNewToken().catch((error) => {
                                localStorage.clear();
                                // Handle token refresh errors e.g clear stored tokens, redirect to login
                                return;
                            })
                        )
                            .filter((value) => Boolean(value))
                            .flatMap(({accessToken, refreshToken}) => {

                                const oldHeaders = operation.getContext().headers;
                                // modify the operation context with a new token
                                operation.setContext({
                                    headers: {
                                        ...oldHeaders,
                                        authorization: `Bearer ${accessToken}`,
                                    },
                                });

                                // retry the request, returning the new observable
                                return forward(operation);
                            });
                   

                }
            }
        }
    }
);



const authLink = setContext((_, { headers }) => {
  return {
    headers: {
      ...headers,
      authorization: localStorage.getItem("AUTHORIZATION") ? `Bearer ${localStorage.getItem("AUTHORIZATION")}` : "",
    },
  };
});




const client = new ApolloClient({
  link: ApolloLink.from([errorLink,authLink, httpLink]),
})

问题是: 成功刷新令牌后,它不会重新获取我的 useQuery 中的数据

顺便说一句,它又做了一个失败的请求,我不知道为什么

【问题讨论】:

  • 你需要使用 useLazyQuery 。例如。您有一个调用 useQuery 的组件,然后一旦组件安装,useQuery 就会运行并从服务器获取数据。但是,如果您在该组件中使用 useLazyQuery 而不是 useQuery,则查询不会运行,并且在组件挂载时不会获取数据。相反,您可以根据您的要求运行查询,例如在您获得刷新令牌后或单击按钮时。

标签: reactjs graphql jwt next.js apollo


【解决方案1】:

您可以使用retry link 再次运行查询。

您应该以重试链接是最外层链接的方式链接您的链接,以便您可以等待错误链接获取令牌。查看custom strategies,您可以在此处对错误对象中的特定状态代码做出反应,或者收听自定义属性,错误链接可以附加到operation 对象。这样,如果令牌刷新失败(例如,因为重新获取令牌也超时),您甚至可以防止重新获取。

这些链接也是开源的,所以如果链接它们对你不起作用,你也可以通过结合两个链接的代码来开发你自己的 refetch+retry 链接。

【讨论】:

    猜你喜欢
    • 2020-08-03
    • 2020-08-25
    • 2019-12-01
    • 2020-08-27
    • 2021-03-07
    • 1970-01-01
    • 2022-10-31
    • 2022-12-23
    • 2021-08-20
    相关资源
    最近更新 更多