Polling
data-init fetches once on load and data-on-interval__duration.5s
re-fetches every five seconds. The endpoint renders the same
<ServerTime/> component the page used for its loading state; the morph
swaps it in place.
Server clock
Loading server time…
Re-fetch by convention
data-on:* listens for any DOM event, so re-fetching is a convention rather than a plugin: give a region data-on:refetch="@get(…)" and dispatch a bubbling CustomEvent('refetch') at it from anywhere.
<div data-on:refetch="@get('/api/time')">
<button data-on:click="evt.target.dispatchEvent(new CustomEvent('refetch', {bubbles: true}))">
Refresh now
</button>
</div>
The shared component
---
/** Server-time fragment shared by the polling page and /api/time. */
interface Props {
time?: string;
}
const { time } = Astro.props;
---
{
time ? (
<div id="server-time">
Server time: <strong>{time}</strong>
</div>
) : (
<div id="server-time" class="hint">
Loading server time…
</div>
)
}The endpoint
import { html } from '@wrux/astro-datastar/server';
import type { APIRoute } from 'astro';
import { experimental_AstroContainer as AstroContainer } from 'astro/container';
import ServerTime from '../../components/ServerTime.astro';
export const prerender = false;
export const GET: APIRoute = async () => {
const container = await AstroContainer.create();
return html(
await container.renderToString(ServerTime, {
props: { time: new Date().toLocaleTimeString('en-GB') },
}),
);
};