+onRenderClient() hook
The onRenderClient() hook defines how pages are rendered/hydrated on the client-side.
The hooks onRenderClient() and onRenderHtml() are essentially the glue code between Vike and your UI framework (React/Vue/Solid/...).
If you use a UI framework Vike extension
vike-react/vike-vue/vike-solid, then you don't need to (and shouldn't) defineonRenderClient()as it's already defined byvike-react/vike-vue/vike-solid.
// +onRenderClient.js
// Environment: client
export { onRenderClient }
import { renderToDom, hydrateDom } from 'some-ui-framework'
async function onRenderClient(pageContext) {
const { Page } = pageContext
// SPA:
await renderToDom(Page)
// SSR:
await hydrateDom(Page)
}// +onRenderClient.ts
// Environment: client
export { onRenderClient }
import type { PageContextClient } from 'vike/types'
import { renderToDom, hydrateDom } from 'some-ui-framework'
async function onRenderClient(pageContext: PageContextClient) {
const { Page } = pageContext
// SPA:
await renderToDom(Page)
// SSR:
await hydrateDom(Page)
}Where:
pageContext.Pageis the+Pagevalue of the page that is being rendered.pageContextis a subset of thepageContextdefined on the server-side.
You can use passToClient to determine what subset of pageContext is sent to the browser.
You should resolve
onRenderClient()only after the page is rendered and visible to the user, because Vike then triggers actions such as setting the scroll position and calling the+onPageTransitionEndhook (typically used for page transition animations).
See Render Modes (SPA, SSR, SSG, HTML-only) and Client Routing for illustrations of conditional DOM hydration, for supporting both SPA and SSR.
SPA vs SSR
When implementing SSR, the client-side onRenderClient() hook works in tandem with the
server-side onRenderHtml() hook: the server-side onRenderHtml()
hook renders the page to HTML and the client-side onRenderClient() hook hydrates the
HTML.
When implementing an SPA, then the client-side onRenderClient() hook is solely responsible for rendering the page.
(There is still a server-side onRenderHtml() hook but it only renders the HTML shell; it doesn't render
pageContext.Page to HTML.)
See Render Modes (SPA, SSR, SSG, HTML-only).
Multiple onRenderClient() hooks
If you create /pages/star-wars/+onRenderClient.js then you define how /pages/star-wars/+Page.js is rendered while overriding the global onRenderClient() hook.
By defining multiple onRenderClient() hooks, you can define different renderings for different pages. See Multiple renderer/.
Abort
Upon client-side navigation, Vike waits for the previous onRenderClient() call to finish before rendering the next page.
To prevent the previous onRenderClient() call from delaying the next page, you can use pageContext.abortSignal to abort it:
// +onRenderClient.js
// Environment: client
import { renderToDom } from 'some-ui-framework'
export async function onRenderClient(pageContext) {
const { Page } = pageContext
const rendering = renderToDom(Page)
await new Promise((resolve) => {
// Resolve onRenderClient() once the page is rendered:
rendering.onPageRendered(resolve)
// Also resolve (i.e. unblock) if the user navigates to another page:
pageContext.abortSignal.addEventListener('abort', resolve)
})
}// +onRenderClient.ts
// Environment: client
import type { PageContextClient } from 'vike/types'
import { renderToDom } from 'some-ui-framework'
export async function onRenderClient(pageContext: PageContextClient) {
const { Page } = pageContext
const rendering = renderToDom(Page)
await new Promise((resolve) => {
// Resolve onRenderClient() once the page is rendered:
rendering.onPageRendered(resolve)
// Also resolve (i.e. unblock) if the user navigates to another page:
pageContext.abortSignal.addEventListener('abort', resolve)
})
}Your other hooks (e.g.
+data) can also usepageContext.abortSignal, see API >pageContext.abortSignal.