97 lines
2.3 KiB
TypeScript
97 lines
2.3 KiB
TypeScript
import React from 'react'
|
|
import { BrowserRouter, Redirect, Route, Switch } from 'react-router-dom'
|
|
import { prepareRoutes } from './config'
|
|
import RouteDefinition from './Route'
|
|
|
|
const getComponentRoute = (contextPath: string, component: React.ComponentType) => (
|
|
<Route
|
|
exact
|
|
key={contextPath}
|
|
component={component}
|
|
path={contextPath}
|
|
/>
|
|
)
|
|
|
|
const renderRouteConfig = (
|
|
Container: React.ComponentType,
|
|
routes: RouteDefinition[],
|
|
contextPath: string,
|
|
): JSX.Element => {
|
|
// Resolve route config object in React Router v3.
|
|
const children: React.ReactNode[] = []
|
|
|
|
const renderRoute = (item: RouteDefinition, routeContextPath: string) => {
|
|
let newContextPath: string
|
|
|
|
if (/(^\/)|(^\*)/.test(item.path)) {
|
|
newContextPath = item.path
|
|
} else {
|
|
newContextPath = `${routeContextPath}/${item.path}`
|
|
}
|
|
|
|
newContextPath = newContextPath.replace(/\/+/g, '/')
|
|
|
|
if (item.redirect) {
|
|
const route = (
|
|
<Route
|
|
exact
|
|
key={newContextPath}
|
|
render={() => <Redirect to={item.redirect as string} />}
|
|
path={newContextPath}
|
|
/>
|
|
)
|
|
|
|
children.push(route)
|
|
} else if (item.component && item.childRoutes) {
|
|
const routeConfig = renderRouteConfig(item.component, item.childRoutes, newContextPath)
|
|
|
|
children.push(routeConfig)
|
|
} else if (item.component) {
|
|
const route = getComponentRoute(newContextPath, item.component)
|
|
|
|
children.push(route)
|
|
} else if (item.childRoutes) {
|
|
item.childRoutes.forEach(r => renderRoute(r, newContextPath))
|
|
}
|
|
}
|
|
|
|
routes.forEach(item => renderRoute(item, contextPath))
|
|
|
|
// Use Switch as the default container by default
|
|
if (!Container) {
|
|
return (
|
|
<Switch>
|
|
{children as JSX.TChildren[]}
|
|
</Switch>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<Container key={contextPath}>
|
|
<Switch>
|
|
{children as JSX.TChildren[]}
|
|
</Switch>
|
|
</Container>
|
|
)
|
|
}
|
|
|
|
interface Props {
|
|
routeConfig: RouteDefinition[]
|
|
component: React.ComponentType
|
|
baseUrlPath: string
|
|
}
|
|
|
|
const Router: React.FC<Props> = (props: Props) => {
|
|
const { routeConfig, component, baseUrlPath } = props
|
|
|
|
const preparedRoutes = prepareRoutes(routeConfig)
|
|
|
|
return (
|
|
<BrowserRouter>
|
|
{renderRouteConfig(component, preparedRoutes, baseUrlPath)}
|
|
</BrowserRouter>
|
|
)
|
|
}
|
|
|
|
export default Router
|