Felipe Moacir

React 19: Transições, Actions e use()

ReactReact 19Frontend
React 19: Transições, Actions e use()

React 19 traz mudanças radicais na forma de lidar com formulários, transições e data fetching.

useTransition: Agora Automático

No React 18, você marcava transições manualmente:

const [isPending, startTransition] = useTransition();

startTransition(() => {
  setPage(2); // Navegação
});

No React 19, navegações são transições por padrão.

use(): Promises Como Hooks

Nova primitive que permite usar Promises diretamente em componentes:

import { use } from 'react';

async function fetchUser(id) {
  const res = await fetch(`/api/users/${id}`);
  return res.json();
}

function UserProfile({ userPromise }) {
  const user = use(userPromise); // ← Suspende automaticamente
  
  return <h1>{user.name}</h1>;
}

// Parent
<Suspense fallback={<Loading />}>
  <UserProfile userPromise={fetchUser(123)} />
</Suspense>

Não precisa de async/await no componente. use() resolve a Promise.

Server Actions: POST Sem API Routes

No React 19 + Next.js 14, você pode chamar funções do servidor diretamente:

// app/actions.js
'use server';

export async function createPost(formData) {
  const title = formData.get('title');
  
  await db.posts.create({ title });
  
  return { success: true };
}

// app/page.jsx
import { createPost } from './actions';

export default function Page() {
  return (
    <form action={createPost}>
      <input name="title" />
      <button>Create</button>
    </form>
  );
}

Sem fetch(), sem API routes. Só a função.

useOptimistic: UI Otimista

Atualizar a UI antes da resposta do servidor:

import { useOptimistic } from 'react';

function TodoList({ todos }) {
  const [optimisticTodos, addOptimisticTodo] = useOptimistic(
    todos,
    (state, newTodo) => [...state, { ...newTodo, pending: true }]
  );
  
  async function createTodo(formData) {
    const title = formData.get('title');
    
    addOptimisticTodo({ id: Date.now(), title });
    
    await fetch('/api/todos', { 
      method: 'POST', 
      body: JSON.stringify({ title }) 
    });
  }
  
  return (
    <form action={createTodo}>
      <input name="title" />
      <button>Add</button>
      <ul>
        {optimisticTodos.map(todo => (
          <li key={todo.id} style={{ opacity: todo.pending ? 0.5 : 1 }}>
            {todo.title}
          </li>
        ))}
      </ul>
    </form>
  );
}

A todo aparece instantaneamente, antes do fetch terminar.

useFormStatus: Estado de Loading

Hook para status de formulários:

import { useFormStatus } from 'react-dom';

function SubmitButton() {
  const { pending } = useFormStatus();
  
  return (
    <button disabled={pending}>
      {pending ? 'Enviando...' : 'Enviar'}
    </button>
  );
}

function Form() {
  async function handleSubmit(formData) {
    await fetch('/api/submit', { method: 'POST', body: formData });
  }
  
  return (
    <form action={handleSubmit}>
      <input name="email" />
      <SubmitButton />
    </form>
  );
}

ref Como Prop

Não precisa mais de forwardRef:

// React 18
const Input = forwardRef((props, ref) => {
  return <input ref={ref} {...props} />;
});

// React 19
function Input({ ref, ...props }) {
  return <input ref={ref} {...props} />;
}

Metadata no Document

Meta tags como componentes:

function BlogPost({ post }) {
  return (
    <>
      <title>{post.title}</title>
      <meta name="description" content={post.excerpt} />
      <link rel="canonical" href={post.url} />
      
      <article>{post.content}</article>
    </>
  );
}

React insere automaticamente no <head>.

Breaking Changes

⚠️ ReactDOM.render() removido (use createRoot())
⚠️ IE11 não suportado
⚠️ propTypes deprecado (use TypeScript)


Conclusão: React 19 é a maior evolução desde Hooks. Server Actions mudam completamente o jogo.