Erros Comuns de Performance em React Native (E Como Corrigi-los)

Publicado em 16 de Dezembro, 2025 • 8 min de leitura

Após 8+ anos construindo aplicações React Native, vi os mesmos erros de performance se repetirem em inúmeros projetos. A boa notícia? A maioria desses problemas é fácil de corrigir quando você sabe o que procurar. Neste guia, vou mostrar as armadilhas de performance mais comuns e exatamente como resolvê-las.

1. Re-renders Desnecessários: O Assassino Silencioso de Performance

Este é de longe o erro mais comum que vejo. Toda vez que um componente re-renderiza desnecessariamente, seu app faz trabalho desperdiçado, drenando bateria e causando quedas de frames.

O Problema

// ❌ Ruim: Este componente re-renderiza a cada atualização do pai
const UserCard = ({ user, onPress }) => {
  return (
    <TouchableOpacity onPress={() => onPress(user.id)}>
      <Text>{user.name}</Text>
    </TouchableOpacity>
  );
};

Cada re-render do pai recria aquela arrow function do onPress, causando re-render do UserCard mesmo quando os dados do usuário não mudaram.

A Solução

// ✅ Bom: Componente memoizado com callbacks estáveis
const UserCard = React.memo(({ user, onPress }) => {
  return (
    <TouchableOpacity onPress={onPress}>
      <Text>{user.name}</Text>
    </TouchableOpacity>
  );
});

// No componente pai
const handlePress = useCallback((userId) => {
  navigation.navigate('UserDetail', { userId });
}, [navigation]);
Dica Pro: Use o React DevTools Profiler para identificar componentes que re-renderizam frequentemente. Você ficará surpreso com quantos renders desnecessários acontecem em um app típico.

2. Computações Pesadas na Thread Principal

React Native executa JavaScript em uma única thread. Bloqueie essa thread com computações pesadas, e sua UI congela.

O Problema

// ❌ Ruim: Filtro pesado bloqueia a UI
const SearchResults = ({ data, query }) => {
  const filtered = data.filter(item =>
    item.title.toLowerCase().includes(query.toLowerCase())
  );

  return <FlatList data={filtered} .../>;
};

Com 10.000+ itens, esta operação de filtro executa a cada tecla digitada, congelando seu campo de busca.

A Solução

// ✅ Bom: Computação memoizada
const SearchResults = ({ data, query }) => {
  const filtered = useMemo(() => {
    return data.filter(item =>
      item.title.toLowerCase().includes(query.toLowerCase())
    );
  }, [data, query]);

  return <FlatList data={filtered} .../>;
};

Para computações realmente pesadas, considere movê-las para um módulo nativo ou usar bibliotecas como react-native-multithreading.

3. Configuração Incorreta do FlatList

FlatList é poderoso, mas FlatLists mal configurados são uma das principais causas de travamentos no scroll.

Props Críticas que Você Provavelmente Está Esquecendo

// ✅ FlatList Otimizado
<FlatList
  data={items}
  renderItem={renderItem}
  keyExtractor={item => item.id}

  // Otimizações de performance
  removeClippedSubviews={true}
  maxToRenderPerBatch={10}
  updateCellsBatchingPeriod={50}
  initialNumToRender={10}
  windowSize={5}

  // Previne thrashing de layout
  getItemLayout={(data, index) => ({
    length: ITEM_HEIGHT,
    offset: ITEM_HEIGHT * index,
    index,
  })}
/>

O Que Cada Prop Faz

  • removeClippedSubviews: Desmonta componentes fora da tela (grande economia de memória)
  • maxToRenderPerBatch: Limita renders por evento de scroll (scroll mais suave)
  • windowSize: Controla quantas alturas de tela renderizar (balanço entre memória e responsividade)
  • getItemLayout: Pula cálculos caros de layout se todos os itens têm a mesma altura

4. Carregamento de Imagens Sem Otimização

Imagens são frequentemente o maior gargalo de performance em apps mobile. Imagens grandes e não otimizadas podem destruir a performance do seu app.

O Problema

// ❌ Ruim: Imagem em resolução total da API
<Image
  source={{ uri: 'https://api.example.com/image/4k-photo.jpg' }}
  style={{ width: 100, height: 100 }}
/>

Você está baixando uma imagem de 5MB apenas para exibi-la em 100x100 pixels. Desperdício!

A Solução

// ✅ Bom: Use FastImage com dimensionamento adequado
import FastImage from 'react-native-fast-image';

<FastImage
  source={{
    uri: 'https://api.example.com/image/thumbnail-100.jpg',
    priority: FastImage.priority.normal,
  }}
  style={{ width: 100, height: 100 }}
  resizeMode={FastImage.resizeMode.cover}
/>

Melhores práticas:

  • Use react-native-fast-image para melhor cache e performance
  • Solicite imagens no tamanho apropriado da sua API
  • Use formato WebP (80% menor que PNG)
  • Implemente carregamento progressivo de imagens para imagens grandes

5. Problemas de Performance na Navegação

Transições de tela devem ser suaves e instantâneas. Se não são, você provavelmente está cometendo um destes erros.

Carregamento Lazy de Telas Pesadas

// ✅ Bom: Lazy load de imports pesados
const HeavyScreen = lazy(() => import('./screens/HeavyScreen'));

const Stack = createNativeStackNavigator();

function AppNavigator() {
  return (
    <Stack.Navigator>
      <Stack.Screen name="Home" component={HomeScreen} />
      <Stack.Screen name="Heavy" component={HeavyScreen} />
    </Stack.Navigator>
  );
}

Evite Trabalho Durante a Navegação

// ❌ Ruim: Operação pesada bloqueia navegação
navigation.navigate('Details');
performHeavyOperation();

// ✅ Bom: Adie trabalho pesado
navigation.navigate('Details');
requestAnimationFrame(() => {
  performHeavyOperation();
});

6. Console.log em Produção

Isso parece trivial, mas deixar console.logs em produção pode deixar seu app 30-40% mais lento.

A Solução

// No seu arquivo de entrada (index.js)
if (!__DEV__) {
  console.log = () => {};
  console.warn = () => {};
  console.error = () => {};
}

Ou use uma biblioteca de logging adequada como react-native-logs que desabilita automaticamente em produção.

Impacto Real: Um Estudo de Caso

Em um projeto recente, aplicamos estas otimizações a um app de e-commerce com 50.000+ produtos:

  • Antes: 28 FPS em média, 3.2s de tempo de transição de tela
  • Depois: 58 FPS em média, 0.4s de tempo de transição de tela
  • Resultado: 2x de melhoria no engajamento do usuário, 40% de redução em crashes

Medindo Performance

Você não pode melhorar o que não mede. Use estas ferramentas para acompanhar seu progresso:

  • Flipper: React DevTools, Inspetor de Rede, Monitor de Performance
  • React Native Performance Monitor: Contador de FPS integrado (chacoalhe o dispositivo → Show Perf Monitor)
  • Xcode Instruments / Android Profiler: Análise profunda de performance nativa

Conclusão

Problemas de performance em React Native são quase sempre corrigíveis. A chave é saber o que procurar e aplicar as otimizações certas sistematicamente. Comece com as vitórias fáceis (remover console.logs, memoizar componentes) e avance para otimizações mais avançadas.

Lembre-se: 60 FPS deve ser seu baseline, não seu objetivo. Usuários esperam apps suaves, com sensação nativa, e estas otimizações vão te levar até lá.

Precisa de ajuda otimizando seu app React Native? Na ThreadCode, já otimizamos dezenas de apps em produção para atingir 60+ FPS. Entre em contato para uma auditoria de performance gratuita.