我对React和Ionic还很陌生。我试图完成的是创建一条"受保护的路线"。我创建了一个名为AuthContext
:的简单上下文
import { createContext, Dispatch } from 'react';
/**
* Context interface for AuthAuthentication/Authorization
*
* @property isAuthenticated
* @property dispatch
*
* @interface
*/
interface AuthDefaultContext {
isAuthenticated: boolean;
dispatch: Dispatch<any>
}
/**
* Authentication/Authorization context for managing
* authenticating/ed and authorizing/ed users
*/
export const AuthContext = createContext<AuthDefaultContext>({
isAuthenticated: false,
dispatch: () => {}
});
和称为ProtectedRoute
:的FunctionalComponent
interface ProtectedRouteProps {
ProtectedComponent: FunctionComponent,
routePath: string
}
export const ProtectedRoute: FunctionComponent<ProtectedRouteProps> = ({ ProtectedComponent, routePath }) => {
useEffect(() => {
console.log(`loading protected route '${routePath}' with component ${ProtectedComponent.name}`)
}, [ProtectedComponent, routePath] );
return (
<AuthContext.Consumer>
{
({ isAuthenticated }) => (
<Route path={ routePath } render={ () => isAuthenticated ? <ProtectedComponent/> : <Redirect to="/login" /> }/>
)
}
</AuthContext.Consumer>
);
}
在我的主要应用程序组件中,我将IonReactRouter
封装在AuthContext.Provider
中,如下所示:
<IonApp>
<AuthContext.Provider value={{ isAuthenticated: authenticated, dispatch: dispatch }}>
<IonReactRouter>
<IonRouterOutlet>
<Route path="/login" component={ Login } exact={ true } />
<ProtectedRoute routePath="/welcome" ProtectedComponent={ Welcome }/>
<ProtectedRoute routePath="/search" ProtectedComponent={ Dummy }/>
</IonRouterOutlet>
</IonReactRouter>
</AuthContext.Provider>
</IonApp>
我遇到的问题是,上面的内容适用于常规路由和第一个ProtectedRoute,但/search/
不起作用。浏览器url中的uri路径更改为/search
,但虚拟组件不呈现。
我注意到,如果将<IonReactRouter>
&<IonRouterOutlet>
如此:
<IonRouterOutlet>
<IonReactRouter>
.....
</IonReactRouter>
</IonRouterOutlet>
所有路线都可以工作,但会失去IonRouterOutlet
提供的动画效果。Ionics网站上的导航文档有IonReactRouter
包装的IonRouterOutlet
,所以我认为这是正确的实现。
如果我将ProtectedRoute
的更改为仅标准的reactRoute
,则所有路线都可以很好地使用动画。所以问题出在我对ProtectedRoute
组件的实现上,我就是搞不清楚。任何帮助都将不胜感激。非常感谢。
更新:
我仍然没有找到这个问题的解决方案,所以我删除了IonRouterOutlet,这似乎是根本原因。这样做的时候,一切都如预期的那样。我在Ionic论坛上发布了这个问题,所以当/如果我得到答案,我会在这里发布。
谢谢,
IonRouterOutlet希望其子级是Routes或"Route-like",这意味着子级需要拥有与Route相同的基本道具。
因此,对于ProtectedRoute,如果您将传入道具routePath
重命名为path
,将ProtectedComponent
重命名为component
,那么它应该会起作用。
我从你的代码开始,在这里整理了一个工作示例回购:https://github.com/elylucas/ionic-react-protected-route
如果有帮助,请告诉我。
感谢
我发现在IonRouterOutlet
中的Route
上使用render
道具会破坏它
在您的情况下,您必须更换以下部件:
<Route
path={routePath}
render={() => isAuthenticated ? <ProtectedComponent/> : <Redirect to="/login" />}
/>
像这样的东西:
{
isAuthenticated ?
<Route path={routePath} component={ProtectedComponent} /> :
<Redirect to="/login" />
}
我的问题是,我在可重用组件"BasicPage"中嵌套了一些页面,这导致了问题:
interface BasicPage extends RouteComponentProps {
title: string;
renderContent: any;
history: any;
hasMenu: boolean;
backAction?: any;
}
/**
* helper Ionic Page which laysout the framework of the page so
* we dont need to repeat the boilerplate code. We also include
* the router by default to help with page navigation
*/
const BasicPage: React.FC<BasicPage> = ({
title,
renderContent,
history,
hasMenu,
backAction,
}) => {
return (
<>
<IonHeader>
<IonToolbar color="primary">
<IonButtons slot="start">
{hasMenu ? <IonMenuButton /> : null}
{backAction ? <IonBackButton defaultHref="/" text="" /> : null}
</IonButtons>
<IonTitle>{title}</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent>{renderContent(history)}</IonContent>
</>
);
};
export default withRouter(BasicPage);
renderContent
没有呈现我的页面。我还没有弄清楚这是什么原因,但我现在正在努力解决这个问题。