Padrões de Revisão de Código para RN
Checklist de revisão de performance, acessibilidade e limites nativos para PRs do Expo SDK 57. Padronize o que os revisores verificam para que a qualidade escale sem o tech lead em cada diff.
Busque em todas as páginas da documentação
Checklist de revisão de performance, acessibilidade e limites nativos para PRs do Expo SDK 57. Padronize o que os revisores verificam para que a qualidade escale sem o tech lead em cada diff.
Cartão de revisão de PR de referência rápida - cole em
.github/pull_request_template.md.
## Checklist de revisão mobile
### Evidência (mudanças de UI / gesto / a11y)
- [ ] Captura de tela ou gravação do iOS anexada
- [ ] Captura de tela ou gravação do Android anexada
- [ ] Verificação rápida VoiceOver OU TalkBack anotada (qual fluxo)
### Performance
- [ ] Listas usam FlashList/FlatList - não ScrollView para feeds longos
- [ ] `renderItem` / `keyExtractor` estáveis (useCallback ou escopo do módulo)
- [ ] Sem novas importações pesadas em `app/_layout.tsx` sem rota lazy
### Acessibilidade
- [ ] `accessibilityLabel` em controles apenas com ícone
- [ ] `accessibilityRole` corresponde ao comportamento (botão vs link)
- [ ] Tipo dinâmico: layout sobrevive a fontes grandes (ou `maxFontSizeMultiplier` justificado)
### Limite nativo
- [ ] Novas dependências adicionadas via `npx expo install <pkg>`
- [ ] Mudanças em `app.config.ts` / plugin de configuração mencionadas na descrição
- [ ] Classificado: Apenas JS (OTA OK) vs requer `eas build`
- [ ] `npx expo-doctor` verde (link do CI)
### Arquitetura
- [ ] Arquivo de rota fino - lógica em `features/`
- [ ] Sem importações profundas entre limites de features
- [ ] Estado do servidor em TanStack Query - não duplicado em Zustand
### Release (se tocar em eas.json, runtimeVersion, channels)
- [ ] Passos de rollback no ticket / comentário do PR
- [ ] Bump de runtimeVersion justificadoQuando usar isso:
// ❌ Revisor bloqueia - map ScrollView de 200 pedidos
export function OrdersScreenBad() {
const { data } = useOrders();
return (
<ScrollView>
{data?.map((o) => <OrderRow key={o.id} order={o} />)}
</ScrollView>
);
}// ✅ Caminho de aprovação - lista virtualizada + renderItem estável
import { FlashList } from "@shopify/flash-list";
import { useCallback } from "react";
export function OrdersScreen() {
const { data } = useOrders();
const renderItem = useCallback(
({ item }: { item: Order }) => <OrderRow order={item} />,
[]
);
return (
<FlashList
data={data ?? []}
renderItem={renderItem}
keyExtractor={(o) => o.id}
estimatedItemSize={72}
/>
);
}Perguntas do revisor:
renderItem a cada renderização (seta inline)?Veja Melhores Práticas de Performance e Vazamentos de Memória e Troca de Listas.
// ❌ Bloqueio - apenas ícone, sem nome, função errada
<Pressable onPress={onSave}>
<Icon name="check" />
</Pressable>// ✅ Aprovação - nome, função, estado
<Pressable
onPress={onSave}
accessibilityRole="button"
accessibilityLabel="Salvar alterações"
accessibilityState={{ disabled: !dirty, busy: saving }}
>
<Icon name="check" accessible={false} />
</Pressable>Verificação rápida do revisor (30 segundos):
Veja accessibilityLabel & accessibilityRole.
// package.json - revisor verifica expo install, não npm major cru
+ "expo-camera": "~17.0.10"// app.config.ts - stanza de plugin presente
plugins: [
[
"expo-camera",
{
cameraPermission: "Permitir que $(PRODUCT_NAME) escaneie códigos de barras do armazém.",
},
],
],Checklist do revisor:
| Pergunta | Critério de aprovação |
|---|---|
| Seguro para OTA? | Não - módulo nativo; PR marca requires-build |
| Strings de permissão legíveis por humanos? | Sim - a revisão do armazenamento lê estas |
| Teste no Expo Go reivindicado? | Sinaliza enganoso - precisa de cliente de desenvolvimento |
| Links ADR ou ticket para escolha nativa? | Registros de Decisão de Arquitetura |
// ❌ Bloqueio - fetch + ramificação na rota app/
// app/(tabs)/orders.tsx
export default function OrdersRoute() {
const [filter, setFilter] = useState("open");
const { data } = useQuery({ queryKey: ["orders", filter], queryFn: () => fetchOrders(filter) });
return <FlatList data={data} ... />;
}// ✅ Aprovação - rota fina
// app/(tabs)/orders.tsx
export { OrdersScreen as default } from "@/features/orders/screens/OrdersScreen";Alinha-se com Princípios Básicos de Arquitetura Mobile e Feature-Sliced Design para RN.
| Severidade | Exemplos | Ação |
|---|---|---|
| Bloquear | Plugin de permissão ausente; feed ScrollView; segredo em EXPO_PUBLIC_* | Deve ser corrigido antes do merge |
| Solicitar alterações | Props de lista instáveis; rótulo de a11y ausente; importação profunda de feature | Corrigir ou ticket + acompanhamento |
| Comentar | Nomenclatura, refatoração opcional, documentação | A critério do autor |
| Elogiar | Testes, notas de rollback, evidência de matriz de dispositivos | Reforçar comportamento |
Simulador iOS Pro Max apenas - Layout e performance mentem. Correção: Exigir evidência de emulador Android para PRs de UI.
"LGTM" apenas no PR de package.json - Derivação nativa sem plugin. Correção: Seção Native-boundary obrigatória quando alterações no lockfile incluem pacotes nativos expo-*.
Revisando captura de tela do Expo Go para bug de worklet do reanimated - Cliente de desenvolvimento difere. Correção: Link de build de preview no PR.
Aprovando cache Zustand de lista de API - Fonte de verdade duplicada. Correção: Apontar para ADR: Seleção de Gerenciamento de Estado.
Ignorando rollback na mudança de canal eas.json - Usuários errados recebem atualização. Correção: Subseção Release obrigatória.
| Abordagem | Usar Quando | Não Usar Quando |
|---|---|---|
| Checklist de template de PR | Padrão - baixo atrito | Equipes apenas com diff visual totalmente automatizado |
| Danger / bot customizado | Aplicar rótulos de captura de tela | Equipe pequena - custo de manutenção |
| Revisão em par apenas | Migração nativa complexa | Taxa de transferência diária de features |
CODEOWNERS em app.config.ts | Monorepo multi-squad | Sobrecarga de mantenedor solo |
Para PRs de configuração nativa e gestos - sim. Para TSX apenas de cópia, a evidência do dispositivo no PR é suficiente se o CI estiver verde.
Meta de mesmo dia útil para PRs com menos de 400 linhas. Se for mais longo, o autor deve dividir ou agendar um pareamento de revisão.
Alternar por PR está ok; ambas as plataformas devem ser cobertas ao longo do sprint - não apenas iOS.
Pule a revisão linha por linha de .expo/types; verifique se tsc passa e se os parâmetros de rota correspondem ao uso.
Mesmo checklist; seniores escalam itens de arquitetura e limite nativo. Juniores focam em a11y e padrões de lista primeiro - Nivelamento RN Júnior → Pleno.
Versões da Stack: Esta página foi escrita para React 19.2.3, React Native 0.86.0 e Expo SDK 57 (
expo~57.0.4).
Revisado por Chris St. John·Última atualização: 16 de jul. de 2026