Dia 1 — Como o React Native roda

Informatica · Conteudo · publicado em 05/10/2026
Dia 1 de 13

Como o React Native roda

Aula 1

O que e React Native e onde o app roda

O que é React Native

React Native não é outra linguagem. É o mesmo JavaScript — o mesmo let, o mesmo

map, o mesmo Promise — rodando dentro de um aplicativo, em vez de dentro de

uma aba do navegador. O arquivo não muda de sintaxe. Muda o que existe em volta

dele: onde o navegador oferece document e window, o React Native oferece

View, Text e StyleSheet.

OndeO que aparece na telaO que existe em volta
Navegadordiv, p, spandocument, window
React NativeView, Text, ImageStyleSheet, useState, navegação

É a mesma virada que o Node.js fez no 2º trimestre: a linguagem sozinha produz

efeito visível no navegador; aqui o efeito é um componente nativo desenhado pelo

sistema, e para isso existir precisa de um intermediário.

O exemplo desta página é a prova de que View é função. Ele importa os dois

nomes do módulo, imprime typeof de cada um — e o console responde function

para os dois — e só então chama View({ children: 'ola' }) e lê o que voltou.

O que volta tem duas propriedades: .type, que é o nome View de novo, e

.props, que é o objeto que foi passado. Essa forma — um objeto com tipo e

props — é o que o runtime sabe converter em tela.

O runtime no meio

O JavaScript que você escreve não é executado pela máquina virtual do Android nem

pelo motor do iOS. Existe um runtime no meio que traduz a sua chamada em

operação nativa:

  1. Você escreve <View> e o Babel transforma isso numa chamada de função.
  2. O runtime recebe a chamada e monta a árvore de componentes.
  3. Cada folha da árvore vira um componente nativo do sistema.
  4. O sistema desenha na tela.

O detalhe que costuma confundir: View é uma função do JavaScript, não uma

tag. Não existe document.createElement('view') por trás; existe uma função

chamada View que o runtime entende. E por isso View precisa estar importada —

component que não foi importado dá erro de "não está definido", o mesmo erro de

uma variável qualquer.

const { View, Text } = require('react-native');

console.log(typeof View);        // function
console.log(typeof Text);        // function

// o componente devolve um objeto com o tipo e as props, não HTML
const elemento = View({ children: 'ola' });
console.log(elemento.type);      // View

Com Text a leitura é a mesma, com uma camada a mais: rotulo.props.children

devolve 'ola'. A children é a prop que carrega o que foi posto dentro da

tag, e ela vale exatamente o que foi passado — texto se o conteúdo era texto,

elemento se era outro elemento. É por isso que a mesma palavra children

funciona para <Text>ola</Text> e para <View><Text>ola</Text></View>: nos dois

casos o conteúdo entrou por ali.

Android e iOS não recebem a mesma coisa

O mesmo arquivo roda nos dois sistemas, mas o resultado tem diferença de

plataforma: botão no iOS tem o comportamento do iOS, no Android tem o do Android.

Isso é proposital — o app não tenta parecer igual nos dois, ele tenta funcionar

bem em cada um.

Quando algo precisa ser específico de uma plataforma, o código separa os dois

casos em um lugar só:

import { Platform } from 'react-native';

const altura = Platform.OS === 'ios' ? 44 : 48;

Platform.OS vale 'ios' ou 'android'. Esse padrão resolve o detalhe de

espaçamento, sombra e fonte que não batem entre plataformas, sem espalhar

condicional pelo código inteiro. A moral é a mesma do ternário em qualquer

lugar: a pergunta fica escrita uma vez, perto do dado que muda, e o resto do

código lê o resultado.

O que o React Native não é

  • Não é framework. É biblioteca: você escolhe como organizar o projeto, e

não há um único caminho imposto.

  • Não é alternativa ao código nativo. Para aplicativo que precisa de

desempenho muito específico de hardware, Kotlin ou Swift continuam sendo a

escolha.

  • Não roda no navegador. O React roda; o React Native não. View não existe

em página web.

  • Não é Electron. O Electron desenha página web dentro de uma janela; o React

Native desenha componente nativo.

O aplicativo é compilado antes de ir para o aparelho

Não existe duplo clique nem recarga de página. O código JavaScript é embutido

no aplicativo e um motor JavaScript — o Hermes, no React Native atual — executa

esse código dentro do aparelho. É por isso que existe o Metro: ele assiste

seus arquivos e reconstrói o pacote a cada alteração, para o app atualizar sem

compilação completa a cada mudança.

A cadeia completa tem quatro elos, e o quarto é o que costuma ser esquecido: o

arquivo é lido, o Babel converte o JSX, o Metro empacota o resultado, e o motor

executa o pacote dentro do aparelho. Se um elo falha, nenhum dos seguintes roda —

e o sintoma é sempre "a tela não atualizou", mesmo quando o problema está no

primeiro elo. Por isso o Metro mostra o erro antes do aparelho: ele falha antes

de entregar o pacote.

Exemplo

// `View` e uma funcao do JavaScript, nao uma tag de HTML. O exemplo
// mostra isso: chama a funcao e le o que ela devolve.
const { View, Text } = require('react-native');

console.log('View e do tipo:', typeof View);
console.log('Text e do tipo:', typeof Text);

// o componente devolve um objeto com o tipo e as props
const elemento = View({ children: 'ola' });
console.log('o que View devolveu:', elemento.type);
console.log('as props:', elemento.props);

// o mesmo com Text, e olhando o que foi posto dentro
const rotulo = Text({ children: 'ola' });
console.log('o que Text devolveu:', rotulo.type);
console.log('o conteudo:', rotulo.props.children);

Saída real

View e do tipo: function
Text e do tipo: function
o que View devolveu: View
as props: { children: 'ola' }
o que Text devolveu: Text
o conteudo: ola
Aula 2

O primeiro script: console e o terminal

O primeiro script: console e o terminal

O console.log é o que produz efeito visível fora da tela do app. Ele escreve

na saída padrão do processo, e no aparelho essa saída é lida por uma ferramenta:

o Metro, no desenvolvimento, e o monitor de logs do Android Studio ou do

Xcode. É o mesmo método que o terminal do Node já usava, e é por ele que se

descobre o que o código está fazendo quando a tela não mostra o que se esperava.

console.log('primeira saida');
console.log('varias linhas', 'no mesmo log');

Os dois argumentos não têm tratamento especial: console.log junta tudo que

receber com espaço e escreve uma linha. É por isso que console.log(a, b) é mais

fácil de ler do que console.log(a + ' ' + b) quando o valor não é texto.

O exemplo da página mostra os três casos. Um console.log com uma string imprime

só a string. O segundo recebe três argumentos e sai como uma linha só, com

varias partes no mesmo log | com pipe no meio — nada indica onde um argumento

terminou e o outro começou. E o terceiro passa o array inteiro: o console desenha

a lista de objetos com o campo de cada um, quebrando a linha quando o objeto é

longo. Esse terceiro é o mais útil em desenvolvimento, porque mostra a estrutura

inteira em vez de um campo escolhido à mão.

Os quatro métodos que importam

console.log imprime. console.error escreve no fluxo de aviso, e é ele que o

runtime usa para avisar sobre um erro — o Warning que aparece quando falta uma

key na lista vem por esse caminho. console.warn é o aviso sem erro, usado por

depreciação. console.table recebe um array de objetos ou um objeto e desenha a

tabela alinhada, que é a forma rápida de conferir uma lista de tarefas que veio

da API.

console.error('falha ao ler a lista');
console.warn('campo titulo vazio, usando o id');
console.table([{ id: 1, texto: 'estudar' }, { id: 2, texto: 'treinar' }]);

O console.table do exemplo recebe a lista de duas tarefas e desenha a tabela

com uma coluna para cada campo que aparecer em qualquer objeto: id, texto e

feita. A coluna (index) à esquerda é a posição na lista, e ela existe para

caso algum objeto esteja sem id — sem isso a linha ficaria sem nome. Campo

que não existe em todos vira célula vazia, e não erro: é o que acontece quando a

lista mistura formatos.

O detalhe que economiza tempo: **console.error e console.log saem em fluxos

diferentes**. O terminal mostra os dois, mas em lugares diferentes — o aviso vai

para o fluxo de erro. Quando a mensagem precisa aparecer junto do resto da

explicação, o par console.error mais console.log imprime a mesma coisa nos

dois lados. É exatamente o que o exemplo faz: falha ao ler a lista sai no

fluxo de erro, e a linha mensagem de erro: falha ao ler a lista repete o texto

no fluxo normal. São duas mensagens com o mesmo conteúdo em lugares diferentes,

não um erro sendo escrito duas vezes.

Comentário: o que fica fora da execução

// comenta o resto da linha. / / comenta um bloco e pode ocupar várias

linhas. Tudo entre o marcador e o fim do trecho é ignorado, e não aparece em

nenhum fluxo de saída:

// este e o nome do item na lista
/* este bloco explica a regra inteira:
   o filtro so passa as tarefas pendentes. */

Este é o primeiro programa de qualquer material de JavaScript, e o mesmo

comentário vale para o app. Comentário não é decoração: é a resposta para a pergunta que o aluno faz

semanas depois, "por que essa linha existe". A regra prática é escrever o **por

que, não o o quê** — // soma os dois numeros não serve para nada, porque a

próxima linha já diz a soma.

A prova de que comentário não executa está no próprio exemplo: os dois comentários

explicam o item da lista e o filtro, e nenhuma linha do terminal os menciona. O

que aparece depois é o resultado do filter — um array com o objeto de id 1 e

o nome em texto, estudar, porque o segundo item estava marcado como feito. A

lista impressa sai do código que roda, não do código comentado.

Rodar o arquivo

Um script de JavaScript puro roda direto no terminal, sem apparatus — sem CLI,

sem prompt de comando, sem DevTools. É a diferença entre executar script e

depender de ferramenta:

node app.js

A entrada do app em React Native é outra: não é node app.js, é o Metro

recebendo a pasta do projeto e montando o pacote para o aparelho. O Metro é o

bundler do React Native — junta os arquivos, resolve os import e reconstrói

o pacote a cada alteração. Essa reconstrução é o fast refresh: o arquivo

salvo volta para a tela em um segundo ou dois, sem recompilar o aplicativo

inteiro.

O que muda do Node para o React Native é o alvo do console.log. No Node ele

aparece no terminal onde o comando foi digitado; no aparelho ele aparece no

monitor do Metro, no logcat do Android ou no console do Xcode. A consequência

prática é a mesma: a linha que aparece ali é o seu código, e o primeiro lugar a

olhar quando a tela não faz o que o código diz é o console.

Quando o log não aparece

Três casos, e os três têm a mesma resposta: conferir se o console.log está

depois do ponto onde o código falha. Se a exceção acontece antes, a linha nunca

chega a ser executada. E console.log dentro de uma função que ninguém chama

também não imprime — a função existe até alguém chamar, como qualquer outra.

O caso mais comum de todos é o terceiro em forma diferente: o console.log

está no fim do arquivo e não imprime nada. A explicação quase nunca é o

console.log — é que a linha está dentro de uma função ou de um componente que

o runtime ainda não chamou. No app, o componente é desenhado por quem o

chamou, e uma função solta no arquivo não é desenhada por ninguém. Por isso a

primeira coisa a tentar, quando o log some, é subir a linha um nível: colocar o

console.log direto no corpo do componente, fora de qualquer função auxiliar, e

ver se ele volta a aparecer.

Exemplo

// Os metodos de console que o aluno usa no desenvolvimento do app, e a
// diferenca entre console.log e console.error: os dois vao para o terminal,
// mas em fluxos separados.
const tarefas = [
  { id: 1, texto: 'estudar', feita: false },
  { id: 2, texto: 'treinar', feita: true },
];

// console.log aceita varios argumentos e junta com espaco
console.log('primeira saida');
console.log('varias partes', 'no mesmo log', '| com pipe no meio');
console.log('array como texto:', tarefas);

// console.table desenha a tabela alinhada
console.table(tarefas);

// console.warn e aviso sem erro
console.warn('campo texto vazio, usando o id');

// console.error vai para o fluxo de aviso. O `console.log` abaixo repete a
// mesma mensagem no fluxo normal, para a mensagem aparecer junto do texto.
console.error('falha ao ler a lista');
console.log('mensagem de erro:', 'falha ao ler a lista');

// comentario de uma linha e de bloco: nada disso executa
// este e o nome do item na lista
/* este bloco explica a regra inteira:
   o filtro so passa as tarefas pendentes. */

const pendentes = tarefas.filter((tarefa) => !tarefa.feita);
console.log('pendentes:', pendentes.map((tarefa) => tarefa.texto).join(', '));

Saída real

primeira saida
varias partes no mesmo log | com pipe no meio
array como texto: [
  { id: 1, texto: 'estudar', feita: false },
  { id: 2, texto: 'treinar', feita: true }
]
┌─────────┬────┬───────────┬───────┐
│ (index) │ id │ texto     │ feita │
├─────────┼────┼───────────┼───────┤
│ 0       │ 1  │ 'estudar' │ false │
│ 1       │ 2  │ 'treinar' │ true  │
└─────────┴────┴───────────┴───────┘
mensagem de erro: falha ao ler a lista
pendentes: estudar