Laravel Daily's

Building Reactive SPAs with Inertia 3.x: Deferred Props + Polling Without WebSockets

hero image

Building reactive single-page applications often leads developers straight to WebSockets. Setting up socket servers introduces maintenance overhead and infrastructure complexity.

Inertia 3.x changes the equation for modern applications built on a robust php web framework. You can achieve real-time updates without managing persistent socket connections.

Deferred props and polling primitives provide a simpler path. You keep your monolith structure while delivering dynamic interfaces.

Inertia::defer(): Lazy-Loading Non-Critical Data

Initial page loads often crawl because heavy database queries block the response. Heavy stats, recent orders, and analytics slow down the first paint.

Inertia::defer() solves this bottleneck by splitting the payload.

use Inertia\Inertia;

class DashboardController
{
    public function index()
    {
        return Inertia::render('Dashboard/Index', [
            'user' => fn () => auth()->user(),
            'visitors' => fn () => Visitor::today()->count(),
            'stats' => Inertia::defer(fn () => [
                'orders' => Order::latest()->take(10)->get(),
                'revenue' => Order::sum('total'),
            ]),
        ]);
    }
}

The initial response arrives instantly with essential props. Inertia immediately triggers a follow-up request for the deferred data.

Your users see the core interface without waiting for heavy background queries to finish. Essential php developer tools make this pattern seamless across controllers.

The Deferred Component: Fallbacks and Rescue Slots

Handling asynchronous data requires clear visual feedback. Vue 3 components pair with Inertia to manage loading states gracefully.

Dashboard polling and deferred loading illustration

The <Deferred> component wraps your markup and listens for specific prop keys.

<script setup>
import { Deferred } from '@inertiajs/vue3'

const props = defineProps({
  user: Object,
  visitors: Number,
  stats: Object,
})
</script>

<template>
  <div>
    <h1>Welcome, {{ user.name }}</h1>
    <p>Today’s visitors: {{ visitors }}</p>

    <Deferred data="stats" v-slot="{ reloading }">
      <template #fallback>
        <div class="skeleton">Loading stats…</div>
      </template>

      <div>
        <h2>Latest Orders</h2>
        <ul>
          <li v-for="order in stats.orders" :key="order.id">
            #{{ order.id }} – {{ order.total }}
          </li>
        </ul>

        <p>Total revenue: {{ stats.revenue }}</p>
        <p v-if="reloading">Refreshing…</p>
      </div>
    </Deferred>
  </div>
</template>

The #fallback slot renders instantly as a skeleton loader. The default slot displays the data once the secondary request resolves.

The { reloading } flag exposes background updates. Users see subtle indicators when data refreshes without disruptive layout shifts.

Auto-Refreshing with usePoll: Polling Without Complexity

Real-time dashboards need fresh data without manual page reloads. usePoll handles periodic requests with minimal configuration.

<script setup>
import { usePoll } from '@inertiajs/vue3'

const props = defineProps({
  visitors: Number,
  stats: Object,
})

usePoll(5000, {
  only: ['visitors', 'stats'],
})
</script>

Passing an interval in milliseconds triggers automatic partial reloads. Limiting updates with the only option prevents unnecessary data transfer.

The controller executes the exact same closures without extra endpoints. You build reactive interfaces while keeping your codebase clean.

This approach lets you build rest api with php endpoints or leverage standard Inertia controllers with equal ease.

Standalone Requests with useHttp: Beyond Navigation

Traditional SPAs often require API calls outside full page navigation. Inertia 3.x introduces robust tools for standalone requests.

You execute mutations, background submissions, and partial data fetches without leaving your component lifecycle. Error handling and loading states integrate directly into your Vue setup.

<script setup>
import { useHttp } from '@inertiajs/vue3'

const { post, processing } = useHttp()

const submitAction = () => {
  post('/api/action', {
    data: { status: 'active' },
    preserveScroll: true,
  })
}
</script>

These utilities keep your state synchronized. You avoid boilerplate fetch wrappers and custom axios configurations.

Practical Patterns: Live Dashboards and When to Choose Polling

Polling fits predictable intervals where sub-second latency is unnecessary. Admin panels, metrics trackers, and analytics dashboards thrive on polling patterns.

Balancing simplicity and real-time data flow

WebSockets remain necessary for collaborative editing or instant chat applications. Most business dashboards do not require that level of persistent infrastructure.

Polling keeps deployment simple. You deploy standard PHP web applications without managing background daemon processes for socket servers.

Robust Ecosystem and First-Party Tools

Modern web development relies on cohesive ecosystems that eliminate boilerplate. Building robust applications requires tools designed to work together from day one.

Robust ecosystem overview

First-party packages handle caching, queues, and database orchestration out of the box. You focus on shipping features rather than stitching disparate libraries together.

Explore the official documentation to see how Laravel streamlines modern deployment and monitoring.

Conclusion

Inertia 3.x bridges the gap between server-driven monoliths and reactive frontends. Deferred props eliminate initial payload bloat.

Polling replaces complex WebSocket configurations for standard real-time dashboards. You ship faster and maintain simpler infrastructure.

Try these patterns in your next project and let us know how your workflow improves.

Previous
Building an AI-Powered Content Generator with Laravel's AI SDK
Next
Building Resilient SPAs: Error Handling with Inertia 3.x's Rescue Slots and Polling Modes