Halo sobat konsepkoding pada artikel kali ini kita akan mempelajari mengenai cara optimasi performa pada aplikasi React Native. 

Tutorial Optimasi React Native Lengkap!
Tutorial Optimasi React Native Lengkap!



Bagaimana Mekanisme React Native?

Jadi sebelum kita optimasi kita harus tau bagaimana mekanisme React Native. Arsitektur baru di React Native merupakan peningkatan yang bertujuan untuk meningkatkan kinerja dan pengembangan aplikasi React Native. Ini menggantikan mekanisme komunikasi lama antara JavaScript dan kode asli , yang disebut The Bridge, dengan mekanisme baru yang disebut JavaScript Interface (JSI) . Hal ini memungkinkan akses langsung ke objek asli dari JavaScript dan sebaliknya, tanpa serialisasi atau antrian.

Tutorial Optimasi React Native Lengkap!
Tutorial Optimasi React Native Lengkap!



1. Gunakan FlatList atau SectionList untuk menampilkan daftar besar di React Native


Jika Anda memiliki daftar yang besar, merender semua item sekaligus dapat menyebabkan masalah kinerja, namun pemuatan lambat dengan FlatList dapat meningkatkan kinerja.

import React from 'react'
import {FlatList} from 'react-native'

const data = [
  {
    id: 1,
    text: 'First'
  },
  {
    id: 2,
    text: 'Second'
  },
  ...
]

const App = () => {
  const renderItem = ({item}) =>(
    <View>
      <Text>{item.text}</Text>
    </View>
  )
  return (
    <FlatList
      data={data}
      renderItem={renderItem}
      keyExtractor={item => item.id}
    />
  )
}

2. Gunakan useCallback untuk fungsi yang perlu di render tidak berulang!


 useCallback mengembalikan suatu fungsi, kita perlu memanggil fungsi tersebut untuk mendapatkan nilainya. Di sini, kita telah memanggil fungsi dalam hook useEffect dan kemudian merender nilai dalam komponen FlatList.


import React, {useState, useEffect, useCallback} from 'react'
import {FlatList} from 'react-native'
import data from './data'

const App = () => {
  const [values, setValues] = useState([]);
  const rateCompare = 3;

  const valuesCallback = useCallback(() => {
    // supposed computationally intensive calculation
    const result = data.filter((d) => d.rating > rateCompare);
    setValues(result);
  }, [rateCompare, setValues]);

  useEffect(() => {
    valuesCallback();
  }, [valuesCallback]);

  const renderItem = ({ item }) => (
    <View>
      <Text>{item.state}</Text>
    </View>
  );

  return (
    <FlatList
      data={values}
      renderItem={renderItem}
      keyExtractor={item => item.id}
    />
  )
}


3. Gunakan useMemo untuk data atau perhitungan kompleks

useMemo mengembalikan nilai memo dari suatu fungsi. Namun, ini hanya boleh digunakan saat melakukan perhitungan yang mahal .

Misalnya, kita ingin memfilter beberapa data yang berasal dari API berdasarkan ratingnya. Kita dapat mengingat perhitungan untuk menghitung ulang hasilnya hanya ketika nilainya berubah:

const data = [
  {id: 1, state: 'Texas', rating: 4.5},
  {id: 2, state: 'Hawaii', rating: 3},
  {id: 3, state: 'Illinois', rating: 4},
  {id: 4, state: 'Texas', rating: 5},
  {id: 5, state: 'Ohio', rating: 4.5},
  {id: 6, state: 'Louisiana', rating: 3},
  {id: 7, state: 'Texas', rating: 2},
  // ...
  {id: 1000, state: 'Illinois', rating: 4.5},
]


Jika kita ingin memfilter data berdasarkan rating (tanpa memoisasi), kita mungkin menggunakan banyak memori.

Oleh karena itu, kami tidak ingin menghitung ulang nilai secara tidak perlu saat komponen lain dirender ulang. Kami ingin merender ulang atau menghitung ulang hanya ketika peringkat dependen berubah .

Mari kita lihat bagaimana kita bisa mencapainya dengan useMemo :

import React, {useMemo} from 'react'
import {FlatList} from 'react-native'
import data from './data'

const App = () => {
  const rateCompare = 3;

  const computedValue = useMemo(() => {
    // supposed computationally intensive calculation
    const result = data.filter((d) => d.rating > rateCompare);
    return result;
  }, [rateCompare]);

  const renderItem = ({ item }) => (
    <View>
      <Text>{item.state}</Text>
    </View>
  );

  return (
    <FlatList
      data={computedValue}
      renderItem={renderItem}
      keyExtractor={item => item.id}
    />
  )
}

4. Gunakan PureComponent agar tidak merender ulang di ClassComponent!

PureComponent adalah salah satu komponen dalam React yang mirip dengan Component, tetapi dilengkapi dengan implementasi shouldComponentUpdate bawaan yang dioptimalkan untuk performa. PureComponent secara otomatis melakukan perbandingan dangkal (shallow comparison) antara prop dan state sebelum merender ulang komponen. Jika tidak ada perubahan pada prop atau state yang relevan, PureComponent akan mencegah pembaruan komponen dan karenanya menghemat sumber daya yang tidak perlu.

Contoh penggunaan PureComponent bisa ditemukan dalam aplikasi React yang memiliki komponen-komponen yang memperoleh prop dari state induk atau komponen lain. Berikut contoh sederhana penggunaannya:

import React, { PureComponent } from 'react';

class List extends PureComponent {
  render() {
    const { items } = this.props;
    return (
      <ul>
        {items.map(item => (
          <li key={item.id}>{item.name}</li>
        ))}
      </ul>
    );
  }
}

class App extends React.Component {
  state = {
    items: [
      { id: 1, name: 'Item 1' },
      { id: 2, name: 'Item 2' },
      { id: 3, name: 'Item 3' }
    ]
  };

  handleClick = () => {
    // Contoh perubahan state yang sama
    this.setState(prevState => ({
      items: prevState.items.slice() // Membuat salinan array
    }));
  };

  render() {
    const { items } = this.state;
    return (
      <div>
        <button onClick={this.handleClick}>Klik untuk mengubah state</button>
        <List items={items} />
      </div>
    );
  }
}

export default App;


5. Gunakan Cache untuk Image

Caching adalah solusi lain untuk masalah gambar di aplikasi React Native. Ini menyimpan gambar secara lokal saat pertama kali dimuat dan menggunakan cache lokal dalam permintaan berikutnya. Hal ini dapat meningkatkan kinerja aplikasi secara signifikan.

Inilah cara Anda menyimpan gambar dalam cache:

<Image
  source={{
    uri: 'https://unsplash.it/200/200?image=8'
    cache: 'only-if-cached'
  }}
  style={{ ... }}
/>
Namun, metode caching ini kurang optimal karena sulit menyelesaikan masalah. Beberapa masalah, seperti kedipan, cache hilang, kinerja aplikasi buruk, dan pemuatan kinerja buruk dari cache, mungkin terjadi saat gambar di-cache dengan cara ini. Masalah ini dapat diatasi dengan react-native-fast-image .

Selain menyimpan gambar dalam cache, FastImage juga menambahkan header otorisasi dan beberapa fitur lainnya:

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

const App = () => (
  <FastImage
    style={{ ... }}
    source={{
      uri: 'https://unsplash.it/200/200?image=8',
      priority: FastImage.priority.normal,
      cache: FastImage.cacheControl.cacheOnly
    }}
  />
)


6. Jadwalkan animasi dengan InteractionManager dan LayoutAnimation


Jika tidak dilakukan dengan benar, animasi dapat mempengaruhi kinerja aplikasi React Native Anda. Metode runAfterInteractions dari InteractionManager dapat digunakan untuk menjadwalkan operasi sinkron yang berjalan lama setelah animasi atau interaksi selesai. Hal ini dapat meningkatkan kinerja aplikasi React Native dengan memastikan animasi berjalan lancar:

InteractionManager.runAfterInteractions(() => {
  // ...
});
Jika Anda mengkhawatirkan pengalaman pengguna, mungkin lebih baik menggunakan LayoutAnimation saja . Ini akan menjalankan animasi pada tata letak berikutnya:

import React, {useState} from 'react'
import {LayoutAnimation} from 'react-native'

if (Platform.OS === 'android' &&
  UIManager.setLayoutAnimationEnabledExperimental
) {
  UIManager.setLayoutAnimationEnabledExperimental(true);
}

const App = () => {
  const [animate, setAnimate] = useState(false)

  const handlePress = () =>{
    LayoutAnimation.configureNext(LayoutAnimation.Presets.spring)
    setAnimate(!animate)
  }
  return (
    <Button onPress={handlePress} title="Animate" />
  )


7. Gunakan Mesin Hermes


Hermes adalah mesin JavaScript yang dikembangkan oleh Facebook pada tahun 2019. Ini adalah salah satu fitur yang harus dimiliki untuk meningkatkan kinerja aplikasi , mengurangi penggunaan memori , mengurangi ukuran aplikasi , dan meningkatkan waktu permulaan aplikasi .

Hermes saat ini diaktifkan secara default di React Native di aplikasi Anda .

Sebelum React Native v0.64 dirilis, Hermes hanya tersedia untuk platform Android, tetapi sekarang juga tersedia untuk iOS .


8. Hindari penggunaan inline style React Native

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

const InlineStyleExample = () => {
  return (
    <View style={{ backgroundColor: 'skyblue', padding: 20 }}>
      <Text style={{ fontSize: 18, color: 'white' }}>Ini adalah teks dengan gaya inline</Text>
    </View>
  );
}

export default InlineStyleExample;

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

const SeparatedStyleExample = () => {
  return (
    <View style={styles.container}>
      <Text style={styles.text}>Ini adalah teks dengan gaya yang dipisahkan</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    backgroundColor: 'skyblue',
    padding: 20,
  },
  text: {
    fontSize: 18,
    color: 'white',
  },
});

export default SeparatedStyleExample;


9. Gunakan driver asli dengan API Animasi

Menjalankan animasi pada thread JavaScript adalah ide yang buruk . Thread JS dapat dengan mudah diblokir dan ini dapat membuat animasi berjalan lambat atau tidak berjalan sama sekali.

Berikut cara menyetel useNativeDriver dengan API Animasi:

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

const App = () => {
  const opacity = useRef(new Animated.value(0)).current

  const showVal = () =>{
    Animated.timing(opacity, {
      toValue: 1,
      duration: 500,
      useNativeDriver: true,
    }).start();
  }

  // ...

  return (
    <View>
      <Animated.View>
        <Animated.Text>Text to show</Animated.Text>
      </Animated.View>
      <Button title="Show" onPress={showVal} />
    </View>
  )
}


10. Jangan gunakan Anonymous Function

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

const AnonymousFunctionExample = () => {
  return (
    <View>
      {/* Penggunaan anonymous function */}
      <TouchableOpacity onPress={() => console.log("Tombol ditekan")}>
        <Text>Tekan saya</Text>
      </TouchableOpacity>
    </View>
  );
}

export default AnonymousFunctionExample;


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

const NonAnonymousFunctionExample = () => {
  // Deklarasi fungsi non-anonymous di luar komponen
  const handlePress = () => {
    console.log("Tombol ditekan");
  };

  return (
    <View>
      {/* Menggunakan fungsi non-anonymous */}
      <TouchableOpacity onPress={handlePress}>
        <Text>Tekan saya</Text>
      </TouchableOpacity>
    </View>
  );
}

export default NonAnonymousFunctionExample;


Sekian artikel mengenai Tutorial Optimasi React Native Lengkap! semoga artikel ini dapat bermanfaat dan membantu kamu yang sedang mempelajari optimasi pada React Native.

Baca Tutorial React Native Lainnya :
#32 Tutorial Kalkulasi Latitude Longitude Dua Jarak React Native
#33 Tutorial React Native Handle OnSwipe Pada iOS
#34 Tutorial View Aspect Ratio Square React Native