Solta

Atualizado a

Porque é que um artefacto React do Claude aparece em branco fora do Claude

Por

No Claude, a janela à volta de um ficheiro React faz quatro trabalhos que o ficheiro não faz sozinho: converte o JSX, fornece os pacotes que os imports nomeiam, monta o componente e carrega o Tailwind. Guardado como ficheiro e aberto num browser, ou posto num alojamento que serve os ficheiros tal como são, nada disso acontece, e o que costuma aparecer é uma página branca.

Cole aqui o ficheiro React que ficou em branco

Veja primeiro a consola

Abra a página, e depois a consola do browser. No Chrome num Mac, é o menu View, depois Developer, depois JavaScript Console, com estes nomes no Chrome em inglês, ou Cmd+Option+J em qualquer idioma; no Windows, Ctrl+Shift+J. A primeira linha a vermelho diz qual destes é:

1. O browser não consegue ler JSX

Uma linha como return <div className="p-8">…</div> é JSX, não JavaScript. Alguma coisa tem de a converter em chamadas de funções antes de um browser a correr. Numa etiqueta <script> normal, o browser não consegue ler o script a partir do primeiro < que não espera, por isso nada do script corre. Guardado como ficheiro .jsx e aberto diretamente, nem sequer corre: o browser mostra o código como texto, ou transfere-o.

A solução é um passo de conversão: um bundler como o Vite ou o esbuild, antes de a página ir para qualquer lado. Para um teste rápido, o Babel consegue converter o JSX no browser com <script type="text/babel">, o que ainda deixa por resolver os imports da secção seguinte.

2. Os imports não apontam para lado nenhum

Os ficheiros React do Claude começam com linhas como estas:

import { useState } from "react";
import { LineChart, Line } from "recharts";
import { Card } from "@/components/ui/card";

No Claude, a janela fornece esses pacotes. Um browser não faz ideia do que é react. Num script de módulo, um nome solto como este é um erro até alguma coisa o associar a um endereço; num script clássico, o próprio import é um erro de sintaxe. O @/ da terceira linha é um atalho de caminho da configuração de um projeto, e o Card que nomeia é um componente do shadcn/ui, um ficheiro que não existe fora do Claude até o adicionar.

A solução é um bundler que instala os pacotes a partir do npm, ou um import map que diz ao browser onde está cada um:

<script type="importmap">
{
  "imports": {
    "react": "https://esm.sh/react@18.3.1",
    "react/jsx-runtime": "https://esm.sh/react@18.3.1/jsx-runtime",
    "react-dom/client": "https://esm.sh/react-dom@18.3.1/client?external=react"
  }
}
</script>

Cada pacote que usa React tem de partilhar a única cópia que a página tem dele, e é isso que ?external=react pede ao esm.sh. Com duas cópias, a página falha com Invalid hook call.

3. Nada monta o componente

O ficheiro do Claude termina com export default function App() { … }. Isso define um componente, mas não o põe na página. No Claude, é a janela que faz esse passo. Sozinho, o ficheiro define uma função que nada chama, o que não é um erro, por isso a consola fica calada e a página fica vazia.

Uma página precisa de um elemento onde desenhar o componente, e de uma chamada que o desenhe:

<div id="root"></div>
<script type="module">
  import { createElement } from "react";
  import { createRoot } from "react-dom/client";
  import App from "./App.js";

  createRoot(document.getElementById("root"))
    .render(createElement(App));
</script>

Aqui App.js é o ficheiro já convertido, não o JSX, e tem de vir de um endereço web (secção 5). Tutoriais mais antigos usam ReactDOM.render em vez disso: o React 18 tornou-o obsoleto e o React 19 removeu-o, por isso num React atual falha com um TypeError.

4. As classes do Tailwind não fazem nada

O Claude dá estilo aos ficheiros React com classes do Tailwind, como className="p-8 rounded-xl bg-slate-900 text-white". No Claude, a janela inclui os estilos do Tailwind. Uma página simples não os inclui, por isso as classes são só nomes.

Este raramente fica completamente em branco: o conteúdo está lá, sem estilo, empilhado junto à margem esquerda. Parece em branco quando o texto devia estar sobre um fundo escuro e agora é branco sobre branco, ou quando o layout depende de classes como h-screen e flex para dar tamanho a alguma coisa.

A solução é o próprio Tailwind. Num build, procura nomes de classes nos seus ficheiros e escreve o CSS que usam. Para um teste rápido há o Play CDN do Tailwind, um script que faz o mesmo no browser, e que a documentação do Tailwind descreve como feito para desenvolvimento, não para produção.

5. A página foi aberta a partir do seu disco

Faça duplo clique num ficheiro HTML e ele abre num endereço file:///. Uma página aí não tem uma origem web própria, e o Chrome e o Edge recusam parte do que ela pede:

  • Um script de módulo de outro ficheiro, <script type="module" src="app.js">. Os scripts de módulo são obtidos segundo as regras de CORS, que uma página file:/// não consegue cumprir.
  • O <script type="text/babel" src="App.jsx"> do Babel, porque o Babel vai buscar esse ficheiro por si e é recusado da mesma forma.
  • Um fetch() de um ficheiro JSON ou CSV que está ao lado da página.

O código escrito dentro da página continua a correr, e os imports de endereços https que o permitem, como o esm.sh, continuam a carregar. A solução é servir a pasta a partir de um servidor web local e abri-la em http://localhost, na porta que o servidor usa: 3000 para o primeiro destes, 8000 para o segundo. Corra qualquer um deles na pasta:

npx serve
python3 -m http.server

Ou salte os cinco

Cole o ficheiro no Solta, na caixa lá em cima. Quando o publica, o Solta converte o JSX, aponta cada import para o esm.sh, com uma versão fixa para os pacotes que estes ficheiros costumam importar, serve os componentes shadcn/ui a partir da sua própria cópia, gera o CSS das classes do Tailwind que o ficheiro usa, e monta o export default numa página. A página é servida num endereço https, por isso as regras do file:/// nunca entram em jogo.

Se o ficheiro não tem export default e não se monta sozinho, o Solta não o publica, e diz o que acrescentar. Se o componente dá erro enquanto é desenhado, a página mostra o erro em vez de uma página branca. O que não consegue resolver é um pacote que o esm.sh não tem, ou qualquer coisa que precise de um servidor: o que não funciona. Uma página que pergunta algo ao Claude enquanto as pessoas a usam também precisa que essa chamada mude: como um site chama um modelo.

Perguntas

Porque é que o meu ficheiro React do Claude mostra uma página em branco?

Porque no Claude a janela à volta dele converte o JSX, fornece os pacotes que os imports nomeiam, monta o componente e carrega o Tailwind. Aberto diretamente num browser, ou num alojamento que serve os ficheiros tal como são, nada disso acontece.

O que quer dizer Unexpected token '<' na consola?

Que o browser encontrou JSX, que não é JavaScript. Tem de ser convertido antes, com um bundler como o Vite ou o esbuild, ou, para um teste rápido, com o Babel no browser.

Como resolver Failed to resolve module specifier "react"?

Com um bundler que instala os pacotes a partir do npm, ou com um import map que diz ao browser onde está cada pacote, por exemplo no esm.sh. Cada pacote que usa React tem de partilhar a mesma cópia dele, senão a página falha com Invalid hook call.

Porque é que a página fica vazia e a consola não mostra nenhum erro?

Porque nada monta o componente: o ficheiro define uma função que nada chama, o que não é um erro. A página precisa de um elemento onde desenhar e de uma chamada a createRoot que desenhe nele o componente.

Porque é que a página não funciona quando abro o ficheiro com duplo clique?

Abre num endereço file:///, e o Chrome e o Edge recusam um script de módulo de outro ficheiro e um fetch() de um ficheiro ao lado. Sirva a pasta a partir de um servidor local, com npx serve ou python3 -m http.server, e abra-a em http://localhost.

Publique diretamente a partir do seu chat de IA

Ligue o Solta ao Claude ou ao ChatGPT e peça: o site fica online com um link, sem copiar código.