刷新令牌时 Apollo Graphql 不更新 useQuery
Apollo Graphql when refreshing token doesn't update useQuery
我面临下一个问题:
我有一个用于获取 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
阿波罗-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 中重新获取数据
顺便说一句,它又做了一个失败的请求,我不知道为什么
您可以使用retry link再次运行查询。
您应该以重试 link 最外 link 的方式链接您的 link,这样您就可以等待错误 link 获取令牌。查看 custom strategies,您可以在此处对错误对象中的特定状态代码做出反应或收听自定义 属性,错误 link 可以附加到 operation
目的。这样您甚至可以在令牌刷新失败时阻止重新获取(例如,因为重新获取令牌也超时)。
link 也都是开源的,所以如果链接它们对你来说真的不起作用,你也可以开发自己的 refetch+retry link 通过结合两者的代码 links.
我面临下一个问题: 我有一个用于获取 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
阿波罗-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 中重新获取数据
顺便说一句,它又做了一个失败的请求,我不知道为什么
您可以使用retry link再次运行查询。
您应该以重试 link 最外 link 的方式链接您的 link,这样您就可以等待错误 link 获取令牌。查看 custom strategies,您可以在此处对错误对象中的特定状态代码做出反应或收听自定义 属性,错误 link 可以附加到 operation
目的。这样您甚至可以在令牌刷新失败时阻止重新获取(例如,因为重新获取令牌也超时)。
link 也都是开源的,所以如果链接它们对你来说真的不起作用,你也可以开发自己的 refetch+retry link 通过结合两者的代码 links.