Olha só o que acabou de sair do forno 🔥
E aí, dev! Se você acompanha o canal experimental do React desde o ano passado, já sabe os dois nomes que estavam na fila: View Transitions e Fragment Refs. Pois é — no React 19.3, os dois finalmente ficaram estáveis e já estão no npm.
Mas tem mais coisa boa nesse release. A gente ganhou uma API browser() de primeira classe pra sair do SSR quando precisar, integração com Trusted Types (aquela camada de segurança contra XSS), e agora Server Components podem renderizar Context direto, sem aquele Provider wrapper chato.
Bora passar por cada feature com código que você pode jogar direto no projeto. Essa análise é baseada no anúncio oficial do React 19.3.
Resumo rápido: View Transitions e Fragment Refs estão estáveis.
use(browser())substitui o hack douseEffectcomsetMounted. Trusted Types agora funcionam out-of-the-box.

1. View Transitions: animação sem pagar o pedágio do Framer Motion
O novo componente <ViewTransition> deixa você animar elementos quando entram, saem, se movem ou redimensionam, usando a View Transition API nativa do browser.
import { ViewTransition, useState, startTransition } from 'react';
import { Video } from './Video';
import videos from './data';
export default function Component() {
const [showItem, setShowItem] = useState(false);
return (
<>
<button
onClick={() => {
// Importante: só anima se a atualização estiver dentro de startTransition
startTransition(() => {
setShowItem((prev) => !prev);
});
}}
>
{showItem ? '➖' : '➕'}
</button>
{showItem && (
<ViewTransition>
<Video />
</ViewTransition>
)}
</>
);
}
Regra de ouro: só atualizações dentro de startTransition, useDeferredValue ou um reveal do <ViewTransition> vão animar. Atualizações urgentes (tipo digitar num input) pulam a animação de propósito.
addTransitionType — mesmo estado, animação diferente
Navegar um carrossel pra frente ou pra trás muda o mesmo currentSlide — mas deveria animar em direções opostas. O addTransitionType resolve isso:
function nextSlide() {
startTransition(() => {
addTransitionType('next');
setCurrentSlide(c => c + 1);
});
}
Depois você escopa a animação no CSS com :active-view-transition-type(next).
Suspense + View Transitions: do jeito certo
Envolver um Suspense boundary em <ViewTransition> deixa o React animar a transição fallback → conteúdo. Mas cuidado — o próprio release notes avisa pra não animar UI cacheada. Os princípios recomendados:
- Fallbacks aparecem imediatamente (sem animação)
- Fallback → conteúdo final deve animar
- Filhos que não suspendem aparecem na hora
<Suspense fallback={<VideoPlaceholder />}>
<ViewTransition update="auto" enter="none" exit="none">
<LazyVideo />
</ViewTransition>
</Suspense>
Você também pode envolver <img> ou fontes em <ViewTransition> pra forçar Suspense enquanto carregam — ou seja, o componente espera imagem, fonte e dados juntos, em vez de cada um aparecer piscando quando termina.

2. Fragment Refs — controle de DOM sem wrapper
O problema clássico: você renderiza uma lista de irmãos sem pai único, e precisa anexar um event listener ou mover o foco. Antes, ou você colocava um <div> wrapper (quebrando o layout) ou modificava um componente de terceiros (impossível).
Fragment Refs resolvem isso te dando um FragmentInstance:
function Component() {
const fragmentRef = useRef(null);
useEffect(() => {
const fragmentInstance = fragmentRef.current;
fragmentInstance.focus(); // Move o foco pro primeiro filho
}, []);
return (
<Fragment ref={fragmentRef}>
{posts.map(post => (
<div key={post.id}>{post.title}</div>
))}
</Fragment>
);
}
O FragmentInstance expõe um conjunto curado de métodos DOM: addEventListener, focus, focusLast, blur, observeUsing (IntersectionObserver/ResizeObserver), getClientRects, scrollIntoView e mais. É uma API restrita de propósito — o React não tá te entregando o DOM inteiro.
3. use(browser()) — o escape hatch de SSR que a gente merecia
O padrão do useEffect com flag mounted morreu. O React 19.3 traz browser() do react-dom:
import { use } from 'react';
import { browser } from 'react-dom';
function TimeZone() {
use(browser()); // Suspende no servidor, renderiza direto no cliente
const timeZone = new Intl.DateTimeFormat().resolvedOptions().timeZone;
return <span>{timeZone}</span>;
}
No servidor, use(browser()) dispara Suspense — o fallback aparece no HTML inicial. No cliente, não suspende, então o componente renderiza normal depois da hidratação.
Detalhe importante: diferente de outros hooks, use() pode ser chamado condicionalmente ou depois de um early return. Ou seja:
function useBrowserQuery(query, options) {
if (options.initialData === undefined) {
use(browser()); // Só sai do SSR quando não tem dado inicial
}
return useQuery(query, options);
}
4. Suporte a Trusted Types (segurança)
Se seu site usa Content-Security-Policy: require-trusted-types-for 'script', o React antes quebrava Trusted Types forçando '' + value. Agora o React 19.3 passa objetos TrustedHTML / TrustedScript / TrustedScriptURL sem coerção. É uma vitória silenciosa de segurança — sem migração necessária.
5. Server Components podem renderizar Context direto
Chega de Provider wrapper de mentira. Server Components agora podem importar e renderizar Context de um módulo 'use client' direto:
// server-component.js
import { UserContext } from './user-context';
export async function Layout({ children }) {
const currentUser = await getCurrentUser();
return (
<UserContext value={currentUser}>
{children}
</UserContext>
);
}
⚠️ Limitações e avisos
- View Transitions são só DOM. Suporte a React Native tá em andamento, mas não saiu.
- Animar UI cacheada de Suspense é anti-pattern. O release notes avisa explicitamente — você vai ver flicker em cada re-render.
use(browser())não é ferramenta de data fetching. É pra optar por sair do SSR em componentes que realmente não conseguem renderizar no servidor (localStorage, timezone, APIs só do browser).- Fragment Refs não são um ref de DOM completo. Você ganha um conjunto curado de métodos, não o node cru.
- Breaking change no Strict Mode: Effects agora são invocados em dobro durante a hidratação pra bater com client-rendered roots. Se sua lógica de hidratação tem side effects, audita isso.
📚 Próximos passos
- Roda
npm install react@19.3 react-dom@19.3e confere o Changelog completo. - Começa pelo
use(browser())— é a migração de menor risco e remove mais boilerplate. - Prototipa View Transitions numa rota de baixo tráfego antes de soltar no app todo.
- Se você usa CSP com Trusted Types, valida agora se suas policies de sanitização funcionam end-to-end.
Se você tá construindo apps React com IA, a mesma cadência de release importa no backend também — dá uma olhada no nosso breakdown sobre rodar agentes de IA prontos pra produção com Gemini 3 e frameworks open-source. E se você tá pesando a ética de shippar comportamentos autônomos de UI, esse texto sobre design de whistleblower de IA e segurança contra insider-threat vale a leitura.

Conclusão
O React 19.3 é um release de estabilidade disfarçado de feature drop. As features principais — View Transitions e Fragment Refs — já estavam nos canais experimentais tempo suficiente pra maioria dos times conhecer o formato. O que importa no 19.3 é que agora dá pra shippar com segurança, com caveats documentados e comportamento previsível.
As duas features silenciosas — use(browser()) e suporte a Trusted Types — vão deletar bastante boilerplate e fechar uma lacuna real de segurança. Se você fizer uma coisa essa semana: procura no seu codebase por useEffect(() => setMounted(true), []) e troca por use(browser()).
Começa pequeno, shippa incremental, e lê o changelog oficial antes de subir pra produção. Valeu, dev! 🚀