Web Standards Framework

Remix

Remix é o framework React focado primeiro em padrões web. Ele se apoia em HTTP, formulários e progressive enhancement para que seu app funcione antes mesmo do JavaScript chegar.

intermediate13 min readUpdated 15 de set. de 2026
posts.$slug.tsx
tsx
// app/routes/posts.$slug.tsx
import { json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";

export async function loader({ params }) {
  const post = await getPost(params.slug);
  if (!post) throw json({ message: "Not found" }, { status: 404 });
  return json({ post });
}

export default function Post() {
  const { post } = useLoaderData();
  return <article>{post.title}</article>;
}
Construído sobre
React
Modelo
Nested routes
Dados
loaders
Mutações
actions
Filosofia
Web standards first
Agora
Mesclado ao React Router v7

Por que importa

Por que o Remix segue um caminho diferente

Progressive enhancement

Formulários e navegação funcionam sem JavaScript e tornam-se mais rápidos e fluidos assim que ele é carregado.

Nested routes com dados

Cada rota carrega seus próprios dados e trata seus próprios erros, em paralelo com suas rotas irmãs.

Menos partes móveis

Loaders e actions substituem a confusão habitual de estado no cliente, effects e chamadas de API.

O panorama completo

As três ideias por trás do Remix

Rotas são donas de seus próprios dados, mutações são formulários e tudo degrada graciosamente sem JavaScript.

Routes

Estrutura

Nested routes definem a URL, o layout e a fronteira de dados em um único lugar.

Loaders e actions

Dados

Funções de servidor que leem dados antes da renderização e lidam com mutações de formulários.

Web standards

Fundação

Requisições, respostas, formulários e headers são primitivos da plataforma, não abstrações do framework.

Remix em resumo

O núcleo do Remix

Nested routes

Módulos de rota se aninham para corresponder à hierarquia da UI e carregam dados em paralelo.

Loaders

Funções de servidor que fornecem dados para uma rota antes que ela seja renderizada.

Actions

Funções de servidor que lidam com envios de formulários e mutações.

Forms

Formulários HTML reais que funcionam sem JavaScript e são aprimorados automaticamente.

Error boundaries

Tratamento de erros por rota que mantém o restante da página ativo.

Resource routes

Rotas que retornam dados em vez de UI, úteis para APIs e webhooks.

Uma breve historia

De um Remix da web ao React Router

  1. 2020

    Remix anunciado

    Os criadores do React Router apresentam um framework construído sobre padrões web.

    20
  2. 2021

    Open source

    Remix é lançado publicamente e ganha atenção por seu modelo de carregamento de dados.

    21
  3. 2022

    Remix 1.0 e Shopify

    Lançamento estável, e a Shopify adquire a equipe e adota o Remix.

    22
  4. 2024

    React Router v7

    As ideias do Remix são incorporadas ao React Router, e o Remix torna-se seu modo de framework.

    24
  5. Hoje

    React focado em padrões

    O modelo continua vivo como o modo de framework do React Router, com a mesma filosofia.

    Hoje

O guia completo

Remix: Tudo que voce precisa saber

O que é Remix?

Remix é um framework React construído sobre padrões web. Enquanto muitos frameworks abstraem a plataforma, o Remix se apoia nela: requisições e respostas HTTP, formulários HTML, links, headers e cookies são a base, e o framework os aprimora em vez de substituí-los.

O resultado é uma aplicação que funciona antes mesmo do JavaScript carregar. Formulários são enviados, links navegam e os dados aparecem, porque o servidor está realizando o trabalho. Quando o JavaScript finalmente chega, as mesmas interações tornam-se instantâneas e parciais. Essa propriedade é chamada de progressive enhancement (aprimoramento progressivo), e é a ideia central do Remix.

Em 2024, a equipe do Remix integrou o framework ao React Router v7, onde ele continua existindo como “framework mode”. Os conceitos e APIs permanecem inalterados, portanto, tudo aqui se aplica a ambos.

Rotas aninhadas

As rotas são arquivos dentro de app/routes, e os pontos nos nomes dos arquivos mapeiam para segmentos da URL.

app/routes/
├── _index.tsx              # /
├── posts._index.tsx        # /posts
├── posts.$slug.tsx         # /posts/:slug
├── posts.$slug.edit.tsx    # /posts/:slug/edit
└── api.health.tsx          # /api/health

As rotas são aninhadas para corresponder à UI. Uma rota pai renderiza um layout compartilhado e um <Outlet />, e as rotas filhas são renderizadas dentro dele. Como o Remix conhece toda a árvore de rotas, ele consegue carregar os dados de uma página e de todas as suas rotas aninhadas em paralelo, em vez de em cascata (waterfall).

// app/routes/posts.tsx
import { Outlet } from "@remix-run/react";

export default function PostsLayout() {
  return (
    <div className="posts">
      <h1>Posts</h1>
      <Outlet />
    </div>
  );
}

Loaders

Um loader é uma função de servidor que fornece dados para uma rota antes que ela seja renderizada. Ele é executado no servidor, portanto, pode se comunicar diretamente com um banco de dados.

// app/routes/posts.$slug.tsx
import { json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";

export async function loader({ params }: LoaderFunctionArgs) {
  const post = await getPost(params.slug);
  if (!post) throw json({ message: "Post not found" }, { status: 404 });
  return json({ post });
}

export default function Post() {
  const { post } = useLoaderData<typeof loader>();
  return <article>{post.title}</article>;
}

Não há estado de carregamento (loading state) para gerenciar nem requisições no lado do cliente. O Remix chama o loader no servidor para a renderização inicial e novamente durante a navegação, e o componente recebe os dados de forma síncrona.

Actions e formulários

As mutações são manipuladas por actions, que são funções de servidor vinculadas a uma rota e disparadas por envios de formulários.

// app/routes/posts.new.tsx
import { redirect } from "@remix-run/node";
import { Form } from "@remix-run/react";

export async function action({ request }: ActionFunctionArgs) {
  const data = await request.formData();
  const title = String(data.get("title") ?? "").trim();

  if (!title) return json({ error: "Title is required" }, { status: 400 });

  await createPost(title);
  return redirect("/posts");
}

export default function NewPost() {
  return (
    <Form method="post">
      <input name="title" required />
      <button type="submit">Create</button>
    </Form>
  );
}

Como este é um formulário real, ele funciona sem JavaScript. O Remix intercepta o envio quando o cliente está pronto e revalida automaticamente os loaders afetados, fazendo com que a UI reflita os novos dados sem a necessidade de atualizações manuais de cache.

Error boundaries

Cada rota pode exportar um ErrorBoundary que captura erros de seu loader, action ou componente.

// app/routes/posts.$slug.tsx
import { isRouteErrorResponse, useRouteError } from "@remix-run/react";

export function ErrorBoundary() {
  const error = useRouteError();

  if (isRouteErrorResponse(error) && error.status === 404) {
    return <h1>Post not found</h1>;
  }

  return <h1>Something went wrong</h1>;
}

As boundaries são aninhadas, portanto, um erro em uma rota filha não deixa a página inteira em branco. O layout ao redor permanece funcional, o que proporciona uma experiência muito melhor do que uma tela branca.

Rotas de recurso e padrões web

Uma rota sem um export default é uma resource route: ela retorna dados em vez de UI, o que é ideal para APIs e webhooks.

// app/routes/api.health.tsx
export async function loader() {
  return json({ status: "ok", time: Date.now() });
}

Como o Remix utiliza as Request e Response da plataforma, você pode ler headers, definir cookies, fazer stream de respostas e retornar qualquer código de status sem precisar aprender uma API específica de um framework. Esse conhecimento é transferível diretamente para outros runtimes.

Por que o modelo parece diferente

A maioria dos apps React gerencia dados em effects e os mantém no estado do cliente, sincronizando esse estado de volta para o servidor através de rotas de API. O Remix colapsa essas camadas:

  • A rota é dona de seus dados através de um loader.
  • A rota é dona de suas mutações através de uma action.
  • O servidor detém a fonte da verdade, e o cliente permanece leve.

Menos peças móveis significam menos bugs, menos estado para sincronizar e menos código para escrever. A contrapartida é uma opinião mais forte sobre como os dados fluem, que é exatamente o motivo pelo qual as equipes que o adotam tendem a gostar.

Melhores práticas

  • Busque dados em loaders, não em effects.
  • Realize mutações através de actions e forms, e deixe o Remix revalidar.
  • Use Form e Link do Remix para que o enhancement funcione automaticamente.
  • Exporte um ErrorBoundary em rotas que possam falhar.
  • Mantenha as rotas aninhadas alinhadas com a hierarquia da UI.
  • Use resource routes para APIs e webhooks.
  • Retorne status codes e headers adequados em loaders e actions.

Erros comuns

  • Fazer fetch em useEffect em vez de usar um loader, perdendo a renderização no servidor.
  • Usar fetch para mutações em vez de uma action e revalidar os dados manualmente.
  • Esquecer o <Outlet /> em uma rota de layout pai.
  • Silenciar erros em vez de deixar que as boundaries os manipulem.
  • Fazer over-fetching em um loader pai quando a rota filha deveria ser a dona dos dados.
  • Tratar o Remix como uma SPA client-side e lutar contra o seu modelo de servidor.

Próximos passos

O Remix é a expressão mais forte do conceito “use the platform” no mundo React. Compare-o com o Next.js para conhecer a outra principal abordagem de React, e com o SvelteKit para ver uma filosofia semelhante em outro ecossistema. Reforce seus fundamentos de React, TypeScript e Node.js e, em seguida, construa um pequeno app com um loader, uma action e um error boundary.

Carregando dados

Um loader executa no servidor antes da rota renderizar. Não há estado de carregamento nem requisição do cliente.

Preferir
export async function loader() {
  return json({
    posts: await getPosts(),
  });
}

export default function Posts() {
  const { posts } = useLoaderData();
  return <List items={posts} />;
}
Evitar
export default function Posts() {
  const [posts, setPosts] = useState([]);
  useEffect(() => {
    fetch("/api/posts")
      .then((r) => r.json())
      .then(setPosts);
  }, []);
  return <List items={posts} />;
}

Lidando com mutações

Uma action processa o formulário no servidor. O mesmo formulário funciona com ou sem JavaScript.

Preferir
export async function action({ request }) {
  const data = await request.formData();
  await createPost(data.get("title"));
  return redirect("/posts");
}

<Form method="post">
  <input name="title" />
  <button>Create</button>
</Form>
Evitar
async function onSubmit(e) {
  e.preventDefault();
  await fetch("/api/posts", {
    method: "POST",
    body: JSON.stringify(data),
  });
}

Perguntas frequentes

Perguntas frequentes

Keep learning

Related topics from the roadmap.

$ comecar a aprender

Pronto para aprender Remix?

Nosso tutorial interativo te guia por Remix passo a passo — com quizzes e codigo real que voce pode executar no navegador.