DEV Community

Priscila Oliveira
Priscila Oliveira

Posted 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 AssemblyAI

Automatic Speech Recognition with AssemblyAI

Experience near-human accuracy, low-latency performance, and advanced Speech AI capabilities with AssemblyAI's Speech-to-Text API. Sign up today and get $50 in API credit. No credit card required.

Try the API

Top comments (0)

Sentry mobile image

Improving mobile performance, from slow screens to app start time

Based on our experience working with thousands of mobile developer teams, we developed a mobile monitoring maturity curve.

Read more

👋 Kindness is contagious

Dive into an ocean of knowledge with this thought-provoking post, revered deeply within the supportive DEV Community. Developers of all levels are welcome to join and enhance our collective intelligence.

Saying a simple "thank you" can brighten someone's day. Share your gratitude in the comments below!

On DEV, sharing ideas eases our path and fortifies our community connections. Found this helpful? Sending a quick thanks to the author can be profoundly valued.

Okay