Capítulo 63 de 456
Experimental feature that keeps navigations, RSC fetches, prefetches, and Server Actions pending (instead of throwing) when the network drops, automatically retrying once connectivity returns, plus a hook (useOffline) to surface connectivity state in the UI.
experimental.useOffline: config flag that prevents failed navigation/RSC fetch/prefetch/Server Action from throwing on network failure; keeps the request pending and retries once online.useOffline() hook (from next/offline): returns true when the browser fires an offline event or a Next.js request fails; flips to false after a successful background connectivity check. More reliable than navigator.onLine, which only reflects the OS interface, not actual internet reachability.<Suspense> boundary sit close to uncached data with an App Shell around it; Partial Prefetching makes that shell the unit <Link> prefetches, so it's ready to render offline.loading.tsx gives the same offline behavior at the segment level, as the boundary Next.js prefetches as the route's shell.fetch() calls made directly in a Client Component, or via React Query/SWR, follow their own retry policy — not covered by useOffline's automatic retry.// next.config.ts — enabling offline support alongside Cache Components
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
cacheComponents: true,
partialPrefetching: true,
experimental: {
useOffline: true,
},
}
export default nextConfig
// app/dashboard/connectivity-fallback.tsx — Suspense fallback aware of connectivity
'use client'
import { useOffline } from 'next/offline'
export function ConnectivityFallback() {
const isOffline = useOffline()
return (
<p>
{isOffline
? 'Waiting for connection to load this section...'
: 'Loading...'}
</p>
)
}
useOffline para diferenciar "carregando" de "esperando reconexão" no próprio fallback do Suspense.// app/ping/ping-form.tsx — Server Action retry with offline-aware label
'use client'
import { useState, useTransition } from 'react'
import { useOffline } from 'next/offline'
import { ping } from './actions'
export function PingForm() {
const [pongs, setPongs] = useState<string[]>([])
const [pending, startTransition] = useTransition()
const isOffline = useOffline()
function handleSubmit() {
startTransition(async () => {
const pong = await ping()
setPongs((prev) => [pong, ...prev])
})
}
const label = pending
? isOffline
? 'Pinging (offline, will retry)...'
: 'Pinging...'
: 'Ping'
return (
<form action={handleSubmit}>
<button type="submit" disabled={pending}>
{label}
</button>
</form>
)
}
useOffline + useTransition cobrem o feedback visual.Not applicable — no tabular API reference in this source range.
navigator.onLine para detectar offline real: só reflete a interface de rede do SO, reporta true mesmo sem acesso real à internet (ex: WiFi sem upstream).next build && next start para testar; dev mode não é referência confiável para comportamento offline.<Link> no viewport da página de origem: sem isso o App Shell da rota destino não é prefetched e não fica disponível offline.experimental.useOffline.useOffline retorna false durante SSR e hidratação inicial; o primeiro valor confiável só vem depois do mount no browser.loading.tsx no nível da rota reproduz o mesmo comportamento offline.useOffline no root layout) complementa o fallback local do Suspense para comunicar o estado de conectividade em toda a aplicação.<Suspense> o mais perto possível do dado não-cacheado.