diff --git a/packages/tuono-router/src/components/Matches.tsx b/packages/tuono-router/src/components/Matches.tsx
index 8ae723bb..917e618e 100644
--- a/packages/tuono-router/src/components/Matches.tsx
+++ b/packages/tuono-router/src/components/Matches.tsx
@@ -3,7 +3,12 @@ import { useRouterStore } from '../hooks/useRouterStore'
import { RouteMatch } from './RouteMatch'
import NotFound from './NotFound'
-export function Matches(): JSX.Element {
+interface MatchesProps {
+ // user defined props
+ serverSideProps: any
+}
+
+export function Matches({ serverSideProps }: MatchesProps): JSX.Element {
const location = useRouterStore((st) => st.location)
const router = useRouter()
@@ -13,5 +18,5 @@ export function Matches(): JSX.Element {
return
}
- return
+ return
}
diff --git a/packages/tuono-router/src/components/RouteMatch.tsx b/packages/tuono-router/src/components/RouteMatch.tsx
index 50e5b802..c4c4398b 100644
--- a/packages/tuono-router/src/components/RouteMatch.tsx
+++ b/packages/tuono-router/src/components/RouteMatch.tsx
@@ -1,23 +1,28 @@
import type { Route } from '../route'
+import { useServerSideProps } from '../hooks/useServerSideProps'
interface MatchProps {
route: Route
+ // User defined server side props
+ serverSideProps: any
}
/**
* Returns the route match with the root element if exists
+ *
+ * It handles the fetch of the client side resources
*/
-export const RouteMatch = ({ route }: MatchProps): JSX.Element => {
- if (route.options.hasHandler) {
- console.log('Has rust handler')
- }
+export const RouteMatch = ({
+ route,
+ serverSideProps,
+}: MatchProps): JSX.Element => {
+ const { data, isLoading } = useServerSideProps(route, serverSideProps)
if (!route.isRoot) {
- console.log(route.options)
return route.options.getParentRoute().component({
- children: route.options.component(),
+ children: route.options.component({ data, isLoading }),
})
}
- return route.options.component()
+ return route.options.component({ data, isLoading })
}
diff --git a/packages/tuono-router/src/components/RouterContext.tsx b/packages/tuono-router/src/components/RouterContext.tsx
index 1b0595a8..86973784 100644
--- a/packages/tuono-router/src/components/RouterContext.tsx
+++ b/packages/tuono-router/src/components/RouterContext.tsx
@@ -3,18 +3,18 @@ import type { Router } from '../router'
const routerContext = React.createContext(null!)
-const ROUTER_DOM_CONTEXT = '__TUONO_ROUTER__CONTEXT__'
+const TUONO_CONTEXT = '__TUONO_CONTEXT__'
export function getRouterContext(): any {
if (typeof document === 'undefined') {
return routerContext
}
- if (window[ROUTER_DOM_CONTEXT as any]) {
- return window[ROUTER_DOM_CONTEXT as any]
+ if (window[TUONO_CONTEXT as any]) {
+ return window[TUONO_CONTEXT as any]
}
- window[ROUTER_DOM_CONTEXT as any] = routerContext as any
+ window[TUONO_CONTEXT as any] = routerContext as any
return routerContext
}
diff --git a/packages/tuono-router/src/components/RouterProvider.tsx b/packages/tuono-router/src/components/RouterProvider.tsx
index 0c084cea..71064d53 100644
--- a/packages/tuono-router/src/components/RouterProvider.tsx
+++ b/packages/tuono-router/src/components/RouterProvider.tsx
@@ -45,6 +45,7 @@ interface RouterProviderProps {
interface ServerProps {
router: Location
+ props: any
}
const initRouterStore = (props?: ServerProps): void => {
@@ -74,13 +75,12 @@ const initRouterStore = (props?: ServerProps): void => {
export function RouterProvider({
router,
serverProps,
- ...rest
}: RouterProviderProps): JSX.Element {
initRouterStore(serverProps)
return (
-
-
+
+
)
}
diff --git a/packages/tuono-router/src/hooks/useServerSideProps.tsx b/packages/tuono-router/src/hooks/useServerSideProps.tsx
new file mode 100644
index 00000000..d57a27cb
--- /dev/null
+++ b/packages/tuono-router/src/hooks/useServerSideProps.tsx
@@ -0,0 +1,63 @@
+import { useState, useEffect, useRef } from 'react'
+import type { Route } from '../route'
+
+const isServer = typeof document === 'undefined'
+
+interface UseServerSidePropsReturn {
+ data: any
+ isLoading: boolean
+}
+/*
+ * Use the props provided by the SSR and dehydrate the
+ * props for client side usage.
+ *
+ * In case is a client fetch the remote data API
+ */
+export function useServerSideProps(
+ route: Route,
+ serverSideProps: any,
+): UseServerSidePropsReturn {
+ const isFirstRendering = useRef(true)
+ const [isLoading, setIsLoading] = useState(
+ // Force loading if has handler
+ route.options.hasHandler &&
+ // Avoid loading on the server
+ !isServer &&
+ // Avoid loading if first rendering
+ !isFirstRendering.current,
+ )
+
+ const [data, setData] = useState(
+ serverSideProps || window.__TUONO_SSR_PROPS__.props,
+ )
+
+ useEffect(() => {
+ // First loading just dehydrate since the
+ // props are already bundled by the SSR
+ if (isFirstRendering.current) {
+ isFirstRendering.current = false
+ return
+ }
+ // After client side routing load again the remote data
+ if (route.options.hasHandler && !data) {
+ ;(async (): Promise => {
+ setIsLoading(true)
+ try {
+ const res = await fetch(`/__tuono/data/${route.path}`)
+ setData(await res.json())
+ } catch (error) {
+ // Handle here error
+ } finally {
+ setIsLoading(false)
+ }
+ })()
+ }
+
+ // Clean up the data when changing route
+ return (): void => {
+ setData(undefined)
+ }
+ }, [route.path])
+
+ return { isLoading, data }
+}
diff --git a/packages/tuono-router/src/index.tsx b/packages/tuono-router/src/index.tsx
index 84ec4f37..28266a55 100644
--- a/packages/tuono-router/src/index.tsx
+++ b/packages/tuono-router/src/index.tsx
@@ -1,3 +1,8 @@
+declare global {
+ interface Window {
+ __TUONO_SSR__PROPS__: any
+ }
+}
export { RouterProvider } from './components/RouterProvider'
export { default as Link } from './components/Link'
export { createRouter } from './router'