Skip to content
This repository was archived by the owner on Jul 6, 2025. It is now read-only.

Commit 310132d

Browse files
committed
Improve useDeno rendering
1 parent dcc3926 commit 310132d

File tree

3 files changed

+34
-35
lines changed

3 files changed

+34
-35
lines changed

framework/react/components/ErrorBoundary.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,5 +117,3 @@ export function StatusError({ status, message }: { status: number, message: stri
117117
)
118118
)
119119
}
120-
121-
export class AsyncUseDenoError extends Error { }

framework/react/hooks.ts

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import util from '../../shared/util.ts'
33
import type { RouterURL } from '../../types.ts'
44
import events from '../core/events.ts'
55
import { RouterContext } from './context.ts'
6-
import { AsyncUseDenoError } from './components/ErrorBoundary.ts'
6+
7+
export class AsyncUseDenoError extends Error { }
78

89
/**
910
* `useRouter` allows you to use `RouterURL` obeject of routing
@@ -39,34 +40,26 @@ export function useDeno<T = any>(callback: () => (T | Promise<T>), revalidate?:
3940
const global = globalThis as any
4041
const qs = query.toString()
4142
const dataUrl = 'pagedata://' + [pathname, qs].filter(Boolean).join('?')
42-
const eventName = 'useDeno-' + dataUrl
43-
const key = dataUrl + '#' + id
4443
const expires = typeof revalidate === 'number' && !isNaN(revalidate) ? Date.now() + revalidate * 1000 : 0
45-
const renderingDataCache = global['rendering-' + dataUrl]
46-
if (renderingDataCache && key in renderingDataCache) {
47-
return renderingDataCache[key] // 2+ pass
48-
} else if (util.inDeno) {
44+
45+
if (util.inDeno) {
46+
const renderingData = global['rendering-' + dataUrl]
47+
48+
if (renderingData && id in renderingData) {
49+
return renderingData[id] // 2+ pass
50+
}
51+
4952
const v = callback()
53+
events.emit('useDeno-' + dataUrl, { id, value: v, expires })
54+
// thow an `AsyncUseDenoError` to break current rendering, then re-render
5055
if (v instanceof Promise) {
51-
events.emit(eventName, id, v.then(value => {
52-
if (renderingDataCache) {
53-
renderingDataCache[key] = value
54-
}
55-
events.emit(eventName, id, { value, expires })
56-
}))
57-
// thow an `AsyncUseDenoError` to break current rendering, then re-render
5856
throw new AsyncUseDenoError()
59-
} else {
60-
if (renderingDataCache) {
61-
renderingDataCache[key] = v
62-
}
63-
events.emit(eventName, id, { value: v, expires })
64-
return v
6557
}
58+
59+
renderingData[id] = v
60+
return v
6661
}
67-
if (key in global) {
68-
return global[key].value
69-
}
70-
return null
62+
63+
return global[dataUrl + '#' + id].value ?? null
7164
}, [id, pathname, query])
7265
}

framework/react/renderer.ts

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import type { FrameworkRenderResult } from '../../server/renderer.ts'
55
import type { RouterURL } from '../../types.ts'
66
import events from '../core/events.ts'
77
import { RouterContext, SSRContext } from './context.ts'
8-
import { AsyncUseDenoError, E400MissingComponent, E404Page } from './components/ErrorBoundary.ts'
8+
import { E400MissingComponent, E404Page } from './components/ErrorBoundary.ts'
9+
import { AsyncUseDenoError } from './hooks.ts'
910
import { isLikelyReactComponent } from './helper.ts'
1011
import { createPageProps } from './pageprops.ts'
1112

@@ -35,23 +36,24 @@ export async function render(
3536
}
3637
const qs = url.query.toString()
3738
const dataUrl = 'pagedata://' + [url.pathname, qs].filter(Boolean).join('?')
38-
const asyncCalls: Array<Promise<any>> = []
39+
const asyncCalls: Array<[string, number, Promise<any>]> = []
3940
const data: Record<string, any> = {}
41+
const renderingData: Record<string, any> = {}
4042
const pageProps = createPageProps(nestedPageComponents)
4143
const defer = () => {
4244
delete global['rendering-' + dataUrl]
4345
events.removeAllListeners('useDeno-' + dataUrl)
4446
}
4547

46-
// rendering data cache
47-
global['rendering-' + dataUrl] = {}
48+
// share rendering data
49+
global['rendering-' + dataUrl] = renderingData
4850

4951
// listen `useDeno-*` events to get hooks callback result.
50-
events.on('useDeno-' + dataUrl, (id: string, v: any) => {
51-
if (v instanceof Promise) {
52-
asyncCalls.push(v)
52+
events.on('useDeno-' + dataUrl, ({ id, value, expires }: { id: string, value: any, expires: number }) => {
53+
if (value instanceof Promise) {
54+
asyncCalls.push([id, expires, value])
5355
} else {
54-
data[id] = v
56+
data[id] = { value, expires }
5557
}
5658
})
5759

@@ -78,7 +80,13 @@ export async function render(
7880
while (true) {
7981
try {
8082
if (asyncCalls.length > 0) {
81-
await Promise.all(asyncCalls.splice(0, asyncCalls.length))
83+
const calls = asyncCalls.splice(0, asyncCalls.length)
84+
const datas = await Promise.all(calls.map(a => a[2]))
85+
calls.forEach(([id, expires], i) => {
86+
const value = datas[i]
87+
renderingData[id] = value
88+
data[id] = { value, expires }
89+
})
8290
}
8391
ret.body = renderToString(createElement(
8492
SSRContext.Provider,

0 commit comments

Comments
 (0)