- Não há
div, não háspane nem CSS cascata. Cada elemento de layout muda. localStorage,window,documente a maioria das APIs do navegador simplesmente não existem.flexDirectiontem como padrãocolumn, nãorow. Isso quebra silenciosamente todos os layouts que você escreveu.- Roteamento, manipulação de imagens, formulários e rolagem precisam ter equivalentes nativos.
- Nada disso é difícil individualmente. É a quantidade total que mata projetos do fim de semana.
Construtores de aplicativos web baseados em IA ficaram muito bons rapidamente. Você pode descrever um app para Lovable, v0 ou Bolt e ter um produto web funcional na mesma tarde.
Ao tentar colocá-lo na App Store, você descobre algo que ninguém menciona: um aplicativo web e um aplicativo nativo compartilham uma linguagem, não uma plataforma. Ambos executam JavaScript. Quase nada mais se transfere.
Já fiz essa conversão várias vezes para saber exatamente onde dói. Aqui estão as sete coisas que quebram, na ordem aproximada em que você as encontrará.
1. Todo elemento HTML está fora
Não há div. Não há span. Não há p, h1, button, ul ou img.
O React Native tem seus próprios primitivos, e a mapeação não é um para um:
// Web
<div className="card"">
<h2>Title</h2>
<p>Body text</p>
<img src={url} >
</div>
// React Native
<View style={styles.card}>
<Text style={styles.title}>Title</Text>
<Text>Body text</Text>
<Image source={{ uri: url }} >
</View>
O importante é lembrar: todos os textos devem ser envolvidos em uma tag <Text>. Uma string simples dentro de um <View> resulta em erro. No web, você pode colocar texto onde quiser; aqui é um erro crítico e a falha mais comum.
2. CSS não cascata — e metade dele não existe
O React Native usa um objeto de estilo em JavaScript, não uma folha de estilos. Isso significa:
-
Sem cascata. Um estilo em um elemento pai não é herdado pelos filhos. Definir
fontSizeem uma tagViewe o texto dentro dela ignora essa definição. -
Sem seletores. Sem classes, sem descendentes, sem
:hover, sem consultas de mídia. -
Sem unidades. Números são pixels independentes da densidade. Use
padding: 16, nãopadding: '16px'.
const styles = StyleSheet.create({
card: {
padding: 16,
borderRadius: 12,
backgroundColor: '#fff',
},
});
Também ausentes: float, grid, position: fixed e a maioria das abreviações do modelo de caixa que você está acostumado. Flexbox é o sistema de layout — praticamente o único.
3. flexDirection tem como padrão column
Este é o que silenciosamente destrói tudo.
No web, display: flex tem como padrão flex-direction: row. No React Native, toda tag View já é flex e a direção padrão é column.
Então toda linha horizontal que você construiu na web se empilha verticalmente após a conversão, e você não receberá um erro — apenas uma layout que parece errado em todos os lugares ao mesmo tempo.
// Você precisa ser explícito
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
Budgete uma tarde apenas para isso.
4. APIs do navegador não existem
Não há window. Não há document. Sem localStorage. Sem fetch, sem cookies, sem medição de DOM, sem alert().
A substituição:
| Web | React Native |
|---|---|
localStorage |
AsyncStorage (ou expo-secure-store para qualquer coisa sensível) |
document.querySelector |
refs |
window.location |
Expo Router / React Navigation |
alert() |
Alert.alert() do react-native |
| CSS media queries | useWindowDimensions() |
O fetch sobrevive, o que é uma pequena bênção - sua camada de API portará-se basicamente da mesma forma.
5. O roteamento é um modelo diferente
O roteamento baseado em URL não existe nativamente. Não há barra de endereços e nem objeto history.
Expo Router te leva mais perto do modelo mental web - é baseado em arquivos, então app/profile/[id].tsx mapeia para /profile/42 - mas você ainda tem que pensar em stacks e tabs, não em páginas. Voltar não é "URL anterior", é "desempilhe a pilha".
Ligações profundas também precisam de configuração real em ambos os lados (esquemas URL, Universal Links no iOS, App Links no Android). Isso é um trabalho genuíno sem equivalente na web.
6. Rolagem e listas são explícitas
No web, o conteúdo excede as bordas e o navegador te dá uma barra de rolagem gratuitamente. Em React Native, nada rola a menos que você diga para fazer isso.
<ScrollView>{/* conteúdo curto */}</ScrollView>
<FlatList
data={items}
keyExtractor={(item) => item.id}
renderItem={( item }) => <Row item={item} />}
/>
E use FlatList (ou FlashList) para qualquer coisa longa - ScrollView renderiza todos os filhos de uma vez e irá comprometer a taxa de quadros em uma lista com 500 itens.
7. Formulários e teclados precisam de trabalho real
<input> se torna <TextInput>, e precisa de configuração que o navegador tratava implicitamente: keyboardType, autoCapitalize, autoComplete, secureTextEntry, returnKeyType.
Ao contrário disso, há o próprio teclado. Em um dispositivo móvel, ele cobre fisicamente a parte inferior da tela, então seu botão de envio some atrás dele a menos que você envolva o formulário em KeyboardAvoidingView com diferentes valores de behavior por plataforma.
Não há equivalente web para esse problema, e ele acaba pegando todo mundo uma vez.
O que isso realmente soma
Individualmente, nenhum desses é difícil. Um desenvolvedor React competente pode resolver qualquer um deles em uma hora.
A questão é que há sete deles e eles se acumulam — além de certificados, perfis de provisionamento, capturas de tela em cinco tamanhos de dispositivo, uma etiqueta nutricional de privacidade e um revisor que pode dizer não mesmo assim.
Essa é a razão honesta pela qual tantas aplicações web construídas por IA nunca chegam à loja. A construção foi um fim de semana. A conversão para React Native e o envio são um projeto completamente diferente.
Caso você prefira não fazer esse projeto, o RapidNative converte aplicações Lovable em verdadeiros builds React Native + Expo e lida com a submissão completa para App Store e Play Store — assinatura, capturas de tela, metadados incluídos. Você recebe o código-fonte e mantém a propriedade dele, e se sua aplicação usa Supabase, a versão nativa aponta para o mesmo projeto sem migração.
Qual desses sete te pegou primeiro? Para mim foi flexDirection — passei duas horas convencido de que meus estilos não estavam sendo aplicados em absoluto.

