DEV Community

Priscila Oliveira
Priscila Oliveira

Posted on • Edited on

Como criar um aplicativo React Native eficiente e fluido

Construir um aplicativo React Native que ofereça uma experiência ágil e responsiva é essencial para conquistar os usuários. Seja ao lidar com funcionalidades dinâmicas, interfaces detalhadas ou dados em grande escala, investir na otimização do desempenho é fundamental. Neste guia, exploraremos soluções práticas para tornar seu aplicativo mais rápido e eficiente.

Principais fatores que comprometem o desempenho

Identificar as causas de lentidão no app é o primeiro passo para resolver os problemas. Aqui estão alguns motivos comuns:

Renderizações excessivas: Quando componentes são re-renderizados sem necessidade, o consumo de CPU pode aumentar, afetando a fluidez.

Exemplo prático:

import React, { useState } from 'react';
import { View, Text, Button } from 'react-native';

const Counter = React.memo(({ count }) => {
  return <Text>Contagem: {count}</Text>;
});

const App = () => {
  const [counter, setCounter] = useState(0);
  const [unrelated, setUnrelated] = useState(false);

  return (
    <View>
      <Counter count={counter} />
      <Button title="Incrementar" onPress={() => setCounter((prev) => prev + 1)} />
      <Button title="Ação não relacionada" onPress={() => setUnrelated(!unrelated)} />
    </View>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

Uso inadequado de memória: Armazenar muitos dados ou manter componentes pesados ativos pode sobrecarregar o dispositivo.

Exemplo prático:

import React, { useState } from 'react';
import { View, Text, Button } from 'react-native';

const App = () => {
  const [imageUri, setImageUri] = useState(null);

  const loadImage = () => {
    const uri = 'https://placekitten.com/300/300';
    setImageUri(uri);
  };

  return (
    <View>
      <Button title="Carregar Imagem" onPress={loadImage} />
      {imageUri && <Text>Imagem carregada de: {imageUri}</Text>}
    </View>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

Complexidade nos componentes: Estruturas complicadas ou não otimizadas impactam o tempo de resposta, especialmente em dispositivos com hardware limitado.

Exemplo prático:

import React from 'react';
import { View, Text, Button } from 'react-native';

const Header = () => <Text>Bem-vindo ao App!</Text>;

const Footer = () => <Text>Obrigado por usar o App!</Text>;

const App = () => {
  return (
    <View>
      <Header />
      <Button title="Clique Aqui" onPress={() => alert('Ação executada!')} />
      <Footer />
    </View>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

Gerenciamento ineficiente de dados: Carregar muitos registros simultaneamente pode causar travamentos e atrasos.

Exemplo prático:

import React, { useState } from 'react';
import { View, Text, Button } from 'react-native';

const App = () => {
  const [content, setContent] = useState('');

  const fetchData = async () => {
    const response = await fetch('https://api.adviceslip.com/advice');
    const data = await response.json();
    setContent(data.slip.advice);
  };

  return (
    <View>
      <Button title="Carregar Dica" onPress={fetchData} />
      {content && <Text>{content}</Text>}
    </View>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

Chamadas de API mal planejadas: Buscar informações em excesso ou de forma desordenada reduz a velocidade geral do app.

Exemplo prático:

import React, { useState } from 'react';
import { View, Button, Text } from 'react-native';

const App = () => {
  const [quote, setQuote] = useState('');

  const getQuote = async () => {
    const response = await fetch('https://api.quotable.io/random');
    const data = await response.json();
    setQuote(data.content);
  };

  return (
    <View>
      <Button title="Buscar Citação" onPress={getQuote} />
      {quote && <Text>{quote}</Text>}
    </View>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

Listas otimizadas com FlatList: Ao trabalhar com listas extensas, é importante evitar renderizações desnecessárias. O componente FlatList é ideal para gerenciar grandes volumes de dados, garantindo que apenas os elementos visíveis sejam carregados.

Exemplo prático:

import React from 'react';
import { FlatList, View, Text } from 'react-native';

const items = Array.from({ length: 300 }, (_, i) => ({
  key: String(i),
  label: `Item ${i + 1}`,
}));

const App = () => {
  return (
    <FlatList
      data={items}
      renderItem={({ item }) => (
        <View style={{ padding: 10 }}>
          <Text>{item.label}</Text>
        </View>
      )}
      initialNumToRender={20} // Controla o número de itens iniciais renderizados
      keyExtractor={(item) => item.key}
    />
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

Estratégias adicionais:

  • Utilize getItemLayout para acelerar a rolagem ao informar as dimensões dos itens.
  • Ajuste windowSize para configurar quantos itens adicionais devem ser carregados fora da área visível.

Melhore a renderização com React.memo: O React.memo é uma ferramenta valiosa para evitar renderizações desnecessárias em componentes que recebem props imutáveis ou mudam com pouca frequência.

Exemplo de aplicação:

import React, { memo } from 'react';
import { View, Text } from 'react-native';

const InfoBox = memo(({ title }) => {
    return (
    <View style={{ marginBottom: 10 }}>
      <Text>{title}</Text>
    </View>
  );
});

const App = () => {
  const items = ["Dado 1", "Dado 2", "Dado 3"];

  return (
    <View>
      {items.map((item, index) => (
        <InfoBox key={index} title={item} />
      ))}
    </View>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

Benefícios:

  • Ideal para componentes que recebem apenas valores fixos.
  • Evita renderizações desnecessárias, melhorando o uso de recursos.

Evite recalcular valores: Cálculos complexos podem ser otimizados usando useMemo e useCallback, garantindo que os resultados sejam armazenados e reutilizados até que algo relevante mude.

Cenário comum:

import React, { useMemo } from 'react';
import { View, Text } from 'react-native';

const App = ({ numbers }) => {
  const sum = useMemo(() => {
    console.log("Calculando...");
    return numbers.reduce((acc, n) => acc + n, 0);
  }, [numbers]);

  return (
    <View>
      <Text>Total: {sum}</Text>
    </View>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

Vantagens:

  • Reduz a sobrecarga em cálculos recorrentes.
  • Facilita a leitura e organização do código.

Gerencie imagens de forma inteligente: Carregar imagens pode ser um dos aspectos mais pesados do seu aplicativo. Ferramentas como react-native-fast-image ajudam a implementar caching de maneira eficiente.

Configuração:

import React from 'react';
import FastImage from 'react-native-fast-image';

const App = () => (
  <FastImage
    style={{ width: 100, height: 100 }}
    source={{
      uri: 'https://placekitten.com/100/100',
      priority: FastImage.priority.normal,
    }}
  />
);

export default App;
Enter fullscreen mode Exit fullscreen mode

Por que é importante:

  • Economiza recursos ao reutilizar imagens carregadas anteriormente.
  • Melhora a experiência do usuário ao reduzir o tempo de exibição.

Execute animações de forma fluida: Animações podem ser um desafio para a performance. Configurar useNativeDriver: true permite que as animações sejam processadas na thread nativa, garantindo transições mais suaves.

Exemplo de animação simples:

import React, { useRef } from 'react';
import { Animated, Button, View } from 'react-native';

const App = () => {
  const scale = useRef(new Animated.Value(1)).current;

  const animate = () => {
    Animated.spring(scale, {
      toValue: 1.5,
      friction: 3,
      useNativeDriver: true,
    }).start(() => {
      Animated.spring(scale, {
        toValue: 1,
        useNativeDriver: true,
      }).start();
    });
  };

  return (
    <View>
      <Animated.View style={{ transform: [{ scale }], width: 100, height: 100, backgroundColor: 'blue' }} />
      <Button title="Animação" onPress={animate} />
    </View>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

Recomendações:

  • Prefira threads nativas para evitar travamentos em animações complexas.
  • Use bibliotecas como react-native-reanimated para recursos adicionais.

Conclusão

Com essas estratégias, é possível criar um aplicativo React Native mais ágil e eficiente. Escolha as soluções que se adaptam melhor ao seu projeto, sempre equilibrando otimização e manutenção do código. Um app bem projetado é a chave para conquistar seus usuários e se destacar no mercado!

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read full post →

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more