Files
tuono/packages/router/src/components/Matches.tsx
T

76 lines
2.0 KiB
TypeScript
Raw Normal View History

2024-06-16 11:23:02 +02:00
import * as React from 'react'
2024-07-11 21:43:38 +02:00
import { useInternalRouter } from '../hooks/useInternalRouter'
2024-05-11 15:08:49 +02:00
import { useRouterStore } from '../hooks/useRouterStore'
2024-06-02 12:14:56 +02:00
import type { Route } from '../route'
2024-05-12 17:13:41 +02:00
import { RouteMatch } from './RouteMatch'
2024-05-11 16:08:51 +02:00
import NotFound from './NotFound'
2024-05-11 15:08:49 +02:00
interface MatchesProps {
// user defined props
serverSideProps: any
}
2024-06-02 12:14:56 +02:00
const DYNAMIC_PATH_REGEX = /\[(.*?)\]/
2024-06-23 20:15:33 +02:00
/*
* This function is also implemented on server side to match the bundle
* file to load at the first rendering.
*
* File: crates/tuono_lib/src/payload.rs
*
* Optimizations should occour on both
*/
2024-06-02 12:14:56 +02:00
export function getRouteByPathname(pathname: string): Route | undefined {
2024-07-11 21:43:38 +02:00
const { routesById } = useInternalRouter()
2024-06-02 12:14:56 +02:00
if (routesById[pathname]) return routesById[pathname]
const dynamicRoutes = Object.keys(routesById).filter((route) =>
DYNAMIC_PATH_REGEX.test(route),
)
if (!dynamicRoutes.length) return
const pathSegments = pathname.split('/').filter(Boolean)
let match = undefined
// TODO: Check algo efficiency
for (const dynamicRoute of dynamicRoutes) {
const dynamicRouteSegments = dynamicRoute.split('/').filter(Boolean)
const routeSegmentsCollector: string[] = []
for (let i = 0; i < dynamicRouteSegments.length; i++) {
if (
dynamicRouteSegments[i] === pathSegments[i] ||
DYNAMIC_PATH_REGEX.test(dynamicRouteSegments[i] || '')
) {
routeSegmentsCollector.push(dynamicRouteSegments[i] ?? '')
} else {
break
}
}
if (routeSegmentsCollector.length === pathSegments.length) {
match = `/${routeSegmentsCollector.join('/')}`
break
}
}
if (!match) return
return routesById[match]
}
export function Matches({ serverSideProps }: MatchesProps): JSX.Element {
2024-05-11 15:08:49 +02:00
const location = useRouterStore((st) => st.location)
2024-06-02 12:14:56 +02:00
const route = getRouteByPathname(location.pathname)
2024-05-11 15:08:49 +02:00
2024-05-11 16:08:51 +02:00
if (!route) {
return <NotFound />
}
return <RouteMatch route={route} serverSideProps={serverSideProps} />
2024-05-14 21:23:32 +02:00
}