bpy*_*ner 5 reactjs react-apollo apollo-link
我正在编写一个使用的React应用,apollo-client并且正在apollo-link-error全局捕获身份验证错误。我正在使用createBrowserHistory浏览器历史记录操纵和redux管理我的应用状态。
出现身份验证错误时,我想将用户重定向到/login页面。但是,使用history.push('/login')and forceRefresh:false可以更改URL,但实际上不会在我的应用程序内部导航。
如果我使用forceRefresh:true它可以正常工作,但该应用程序已完全重启,我想避免这种情况。
const errorLink = onError(({ graphQLErrors, networkError }) => {
if(graphQLErrors[0].extensions.code == "UNAUTHENTICATED") {
// with forceRefresh:true this works, but causes a nasty
// reload, without the app doesn't navigate, only the url changes
history.push('/login')
}
});
Run Code Online (Sandbox Code Playgroud)
`
let links = [errorLink, authLink, httpLink];
const link = ApolloLink.from(links);
const client = new ApolloClient({
link: link,
cache: new InMemoryCache(),
connectToDevTools: true,
});
Run Code Online (Sandbox Code Playgroud)
我认为问题是我没有使用redux-router导航方法(因此即使url更改,应用程序也保持不变)
问:当我不在组件内部时,如何获得redux history类似于使用的对象withRouter()?处理这种情况的正确方法是什么?
一种可能的解决方案的简短摘要:
<ProtectedRoute>将未经身份验证的用户重定向到登录页面的组件内。ProtectedRoute-组件仅检查用户是否具有有效令牌,如果没有则重定向用户。location.reload()具体实现如下。
我无法找到任何直接的解决方案。在正常情况下,为了重定向用户,我使用react-router navigator()钩子。在错误链接中我发现无法使用react-hooks。
不过,我还是成功解决了实际问题。我实现了 ProtectedRoute 组件,它包装了应用程序中需要身份验证的所有部分:
type ProtectedRouteProps = {
path: string;
toRedirect: string;
};
export const ProtectedRoute: FunctionComponent<ProtectedRouteProps> = ({
path,
toRedirect,
children,
}) => {
return isAuthenticated() ? (
<Route path={path}>
{children}
</Route>
) : (
<Navigate to={{ pathname: toRedirect }} />
);
};
type ValidToken = string;
type ExpiredToken = 'Expired token'
type NullToken = '' | null
export type JwtTokenType = (ValidToken | ExpiredToken | NullToken )
export const isNullToken = (token: JwtTokenType) : boolean => {
return (token === '' || token === null)
}
export const isExpiredToken = (token: JwtTokenType) : boolean => {
return token === "Expired token"
}
export const isAuthenticated = () : boolean => {
let token = getTokenFromCookies();
return !(isExpiredToken(token) || isNullToken(token));
}
Run Code Online (Sandbox Code Playgroud)
我使用它如下:
<Routes>
<Route path="login" element={<LoginPage />} />
<ProtectedRoute path="/*" toRedirect="login">
// protected routes here
</ProtectedRoute>
</Routes>
Run Code Online (Sandbox Code Playgroud)
为了处理未经身份验证的用户的注销和重定向,我实现了两个函数:
// Use this in normal cases
export function useHandleLogout(): () => void {
const navigate = useNavigate();
// maybe call other hooks
});
function handleLogout() {
navigate("/login");
removeToken();
// do other stuff you want
}
return handleLogout;
}
// Use this inside error-link
export const handleLogoutWithoutHook = () => {
// Logout without hook
removeToken();
// do other stuff required when logout
// eslint-disable-next-line no-restricted-globals
location.reload();
// location.reload() after token removed affects user redirect
// when component is wrapped inside <ProtectedRoute> component
};
export const removeToken = () => {
Cookies.remove("jwt-token")
}
Run Code Online (Sandbox Code Playgroud)
最后在错误链接中:
export const errorLink = onError(
({ graphQLErrors, networkError, operation, forward }) => {
if (graphQLErrors) {
for (let err of graphQLErrors) {
if (err.message.includes('AnonymousUser')) {
handleLogoutWithoutHook()
return
}
if (err.message.includes('Signature has expired')) {
handleLogoutWithoutHook()
}
console.log(err.message)
}
}
return forward(operation)
}
);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
228 次 |
| 最近记录: |