Capítulo 81 de 456
Next.js suporta construir Single-Page Applications (navegação client-side, sem full-page reload) usando padrões próprios — evitando o JS pesado e os data waterfalls de uma "strict SPA" tradicional, com caminho de migração progressivo para features de servidor.
index.html) + zero full-page reloads; costuma exigir muito JS antes de ficar interativa e sofre com data waterfalls no cliente.next/link com prefetch automático: dá transições rápidas como uma strict SPA, mas preserva o estado de rota na URL (compartilhável/linkável).use() + Context Provider: padrão para streamar dado do servidor a um Client Component — inicia o fetch num Server Component (sem await), passa a Promise via provider/context, e o Client Component desembrulha com use(), suspendendo até resolver.React.cache: usado para compartilhar uma única chamada de dado (ex. getUser) entre múltiplos componentes que leem o mesmo dado numa mesma requisição.next/dynamic com ssr: false: desabilita prerender de um Client Component, carregando-o só no browser — útil para libs de terceiros que dependem de window/document.window.history.pushState/replaceState diretamente para atualizar a URL sem reload; essas chamadas se integram ao router do Next.js e sincronizam com usePathname/useSearchParams.useTransition/useOptimistic/useActionState/useFormStatus: ferramentas React para manter a UI responsiva durante uma mutação de servidor, aproximando a sensação de uma SPA client-rendered.import { UserProvider } from './user-provider'
import { getUser } from './user'
export default function RootLayout({ children }: LayoutProps<'/'>) {
let userPromise = getUser() // do NOT await
return (
<html lang="en">
<body>
<UserProvider userPromise={userPromise}>{children}</UserProvider>
</body>
</html>
)
}
'use client'
import { use } from 'react'
import { useUser } from './user-provider'
export function Profile() {
const userPromise = useUser()
const user = use(userPromise)
return <p>{user.name}</p>
}
await e passa a Promise adiante; Client Component desembrulha com use() e suspende até resolver, evitando waterfall client-side.'use client'
import { useTransition } from 'react'
import { deletePost } from './actions'
export function DeletePost({ id }: { id: string }) {
const [isPending, startTransition] = useTransition()
return (
<button disabled={isPending} onClick={() => startTransition(() => deletePost(id))}>
{isPending ? 'Deleting…' : 'Delete'}
</button>
)
}
startTransition e usar isPending para feedback imediato de UI.import dynamic from 'next/dynamic'
const ClientOnlyComponent = dynamic(() => import('./component'), {
ssr: false,
})
await no Server Component + Promise via context + use() no Client Component, dentro de <Suspense>.React.cache evita chamadas duplicadas quando múltiplos componentes leem o mesmo dado numa mesma requisição.window.history.pushState/replaceState é o caminho de migração pra código legado de SPA que já manipulava a URL manualmente (ex. vindo de CRA/Vite).useTransition, useOptimistic, useActionState e useFormStatus.use() e Promise-as-prop cruzam a fronteira servidor/cliente.