DEV Community

Dan E
Dan E

Posted on Originally published at rendex.dev

SPA Screenshot: waitFor Strategies for React, Vue, Svelte

Capturing SPAs: waitFor Strategies for React, Vue, and Svelte

Single-page apps render content after the initial HTML loads. A screenshot taken too early captures a loading spinner or an empty container. The fix is telling the browser to wait for the right signal before the shutter fires.

How wait strategies work

Two parameters control the wait:

  • waitUntil — a network or lifecycle event: "load", "domcontentloaded", "networkidle0", or "networkidle2" (default)
  • waitForSelector — a CSS selector that appears when the content you care about is ready

React

Add a marker element that renders after the app mounts:

// App.tsx
import { useEffect, useState } from "react"

export default function App() {
  const [mounted, setMounted] = useState(false)

  useEffect(() => {
    setMounted(true)
  }, [])

  return (
    <>
      {mounted && <div id="app-loaded" style={{ display: "none" }} />}
      {/* rest of your app */}
    </>
  )
}
Enter fullscreen mode Exit fullscreen mode
// capture.ts
import { Rendex } from "@copperline/rendex"

const rendex = new Rendex(process.env.RENDEX_API_KEY!)

const result = await rendex.screenshot({
  url: "https://myapp.example.com",
  waitForSelector: "#app-loaded",
  waitUntil: "domcontentloaded",
  fullPage: true,
})
Enter fullscreen mode Exit fullscreen mode

Vue 3

<!-- App.vue -->
<script setup>
import { ref, onMounted } from "vue"
const isReady = ref(false)
onMounted(() => { isReady.value = true })
</script>

<template>
  <div v-if="isReady" id="vue-ready" style="display:none" />
</template>
Enter fullscreen mode Exit fullscreen mode
const result = await rendex.screenshot({
  url: "https://vueapp.example.com",
  waitForSelector: "#vue-ready",
  waitUntil: "domcontentloaded",
  fullPage: true,
})
Enter fullscreen mode Exit fullscreen mode

Svelte

For most Svelte apps, networkidle0 is sufficient:

const result = await rendex.screenshot({
  url: "https://svelteapp.example.com",
  waitUntil: "networkidle0",
  fullPage: true,
})
Enter fullscreen mode Exit fullscreen mode

Troubleshooting

Selector never appears and capture times out. Validate in DevTools with document.querySelector('#your-selector'). If it returns null, the element does not exist.

Partial render even with selector. The selector appeared but assets had not loaded. Add a delay in milliseconds or wait for a more specific element.

networkidle0 times out. The page has long-polling or WebSocket connections. Switch to "networkidle2" or use waitForSelector instead.

Next steps

Get a free API key and start with 100 captures per month.

Top comments (0)