Cara Menggunakan SQLite di React Native

Cara Menggunakan SQLite di React Native

Halo semuanya, seneng banget saya bisa posting kembali secara berturut-turut. Hari ini kembali pada konten codecast kita, kita akan sharing cara menggunakan sqlite react native.

Masih di kondisi yang sama, pandemi COVID-19 belum juga selesai. Protokol 3M masih terus dicanangkan untuk memutus rantai. Namun, kelihatannya temen-temen sudah malas hmmm….

Dah, kita kembali pada topik utama. Sebelum kita memasuki gerbang utama dari artikel ini: menggunakan sqlite react native, kita bisa tau dahulu apa itu SQLite dan bagaimana cara kerjanya, serta penggabungannya dengan React Native.

Menggunakan SQLite React Native: Apa itu SQLite?

Logo SQLite CodeSeem
SQLite CodeSeem

Kalo dari Wikipedia, sumber informasi yang agaknya cukup kredibel menurut masyarakat internet, SQLite adalah

SQLite is a relational database management system contained in a C library. In contrast to many other database management systems, SQLite is not a client–server database engine. Rather, it is embedded into the end program.

Wikipedia

Nah, singkatnya dia itu RDBMS yang sistem dan database-nya ditempelkan langsung pada program utama (tidak terpisah seperti MySQL dkk). Dengan begini, kita tidak perlu memiliki DB server yang terpisah lagi.

Dikarenakan kita tidak memiliki DB server lagi, pengimplementasian SQLite pada aplikasi (apalagi pada aplikasi mobile), sering disebut sebagai local storage / offline storage. Kenapa kacang? (why nut?), karena tidak adanya konektivitas dan pertukaran data keluar menuju DB server.

Bagaimana Cara Kerja SQLite?

Cara Kerja SQLite dibanding RDBMS lainnya CodeSeem
Flow SQLite pada aplikasi kita dibanding RDBMS lainnya

Nah, seperti yang telah dijelaskan pada definisinya di atas, kita sudah tau bahwa SQLite ditempelkan pada program utama. Jadi, alih-alih terpisah servernya, sistem SQLite dan file DB-nya justru menempel pada program utama.

Sistem SQLite terpasang pada aplikasi kita, file DB-nya juga dibuat di internal aplikasi kita, proses query data juga kita lakukan pada aplikasi kita. Query language yang digunakan tentu bisa kita tebak. Yapp, kita menggunakan SQL untuk query data.

Tapi, jangan samakan SQLite dengan RDBMS berbasis SQL lainnya. Mengapa ada kata lite pada SQLite? Karena tidak seluruh fitur RDBMS berbasis SQL berada pada SQLite. Contohnya saja, tipe data pada SQLite lebih simpel dari RDBMS berbasis SQL lainnya. Stored procedure juga tidak tersedia.

Terbatasnya fitur SQLite menurut saya bukan tanpa alasan. Sebagai embedded system, pastinya akan menjadi berat kalau seluruh fitur dari RDBMS pada umumnya diterapkan juga disana. Jadi, menurut saya sah-sah saja ya.

Implementasi SQLite pada React Native

Nah, kita masuk pada topik utama kita. Setelah kita tau apa itu SQLite dan bagaimana cara kerjanya, sekarang kita bisa mengetahui cara implementasinya pada React Native Application.

Untuk dapat mengimplementasi SQLite pada projek React Native, kita perlu bantuan library react-native-sqlite-storage. Salah satu library SQLite untuk React Native paling stabil dan populer.

Menggunakan sqlite react native: Menginisiasi Project

Pertama, kita harus menginisiasi projek React Native dahulu. Dalam hal ini saya menggunakan react-native init

npx react-native init codeseemrnsqlite

Setelah itu, kita bisa langsung menginstall dependency yang diperlukan yakni react-native-sqlite-storage.

cd codeseemrnsqlite && npm install --save react-native-sqlite-storage

Untuk React Native versi 0.60+, kita bisa langsung build supaya fitur Auto linking dari React Native berjalan.

npx react-native run-android

Setelah itu, akan nampil tampilan default dari React Native di emulator/device kita seperti dibawah ini.

React Native Welcoming Screen Android CodeSeem

Kemudian, kita modifikasi file App.js supaya memiliki fungsi menampilkan dan menambahkan list data dari state.

/**
 * CodeSeem SQLite React Native Application
 */
import React, { useState } from 'react';
import { View, Text, Button, StyleSheet, TextInput, ScrollView, Alert } from 'react-native';

const App = () => {
  const [value, setValue] = useState('');
  const [listData, setListData] = useState([]);

  const handleAddData = () => {
    if (value) {
      let newListData = listData;
      newListData.push(value);

      setListData(newListData);
      setValue("");
    } else {
      Alert.alert('Info', 'Mohon masukkan data yang benar!')
    }
  }

  return (
    <View style={styles.container}>
      <Text>React Native SQLite</Text>
      <View style={styles.textInputWrapper}>
        <TextInput onChangeText={text => setValue(text)} value={value} placeholder="Masukkan data" style={styles.textInput} />
        <View style={{ margin: 10 }}>
          <Button onPress={handleAddData} title="Add Data" />
        </View>
      </View>
      <Text>List Data</Text>
      <ScrollView>
        {
          listData.map(item => {
            return <Text key={item}>{item}</Text>
          })
        }
      </ScrollView>
    </View>
  )
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20
  },
  textInputWrapper: {
    flexDirection: 'row'
  },
  textInput: {
    flex: 1,
    paddingVertical: 0,
    marginVertical: 10,
    borderWidth: 1,
    borderColor: 'black'
  }
});

export default App;

Code di atas akan menampilkan tampilan seperti di bawah ini. Sudah memiliki fungsi untuk menambah dan menampilkan data, hanya saja belum kita integrasikan dengan SQLite.

Tampilan awal App.js React Native dengan Add Data menggunakan State CodeSeem
Tampilan awal App.js dengan Add Data menggunakan State

Tahan dulu bro, coba liat artikel ini juga da
Cara membuat Read More di WhatsApp menggunakan JavaScript

CodeSeem

Menambahkan Fungsi SQLite

Untuk sharing kali ini, saya menggunakan opsi ‘open pre-populated database’. Jadi, di awal saya membuat file SQLite dahulu. Saya menggunakan Navicat untuk membuat file db SQLite baru.

File database dengan nama codeseem.db yang memiliki satu table ms_user dua kolom (user_id dan user_fullname).

Struktur database SQLite codeseem.db dengan table ms_user
Struktur Database codeseem.db dan Table ms_user

Setelah kita membuat database tersebut, kita bisa langsung membuat direktori baru di project kita. Untuk Android, tambahkan folder baru bernama www di android/app/src/main/assets/www. Kemudian masukkan db yang tadi dibuat ke folder tersebut.

Lokasi database SQLite pre-populated android CodeSeem
Lokasi Database Pre-populated

Setelah itu, kita bisa memodifikasi file App.js supaya bisa loading database kita.

//Tambahkan line ini di awal
import { openDatabase } from 'react-native-sqlite-storage';

var db = openDatabase({name:'codeseem.db', createFromLocation:1}, () => {
  Alert.alert('Info', 'Sukses loading database SQLite');
}, (err) => {
  console.log(err)
})

Disclaimer! Temen-temen harus ingat bahwa file codeseem.db tadi berada di folder android. Apapun yang berubah di folder tersebut, tidak akan terlihat perubahannya pada app, kecuali kita build ulang. Maka kita harus build ulang dengan command dibawah.

npx react-native run-android

Menambah Insert data ke SQLite pada handleAddData

Setelah aplikasi launch, temen-temen seharusnya sudah bisa melihat Alert yang dihasilkan karena callback function di atas. Kalau sudah muncul, berarti database sudah berhasil ter-load.

Kita masih punya pr lagi. Sekarang saatnya kita mengganti function handleAddData supaya bisa menambah dan mengurangi data di database.

const handleAddData = () => {
    if (value) {
      db.transaction((tx) => {
        tx.executeSql(
          'INSERT INTO ms_user (user_fullname) VALUES (?);',
          [value],
          (txn, res) => {
            if (res.rowsAffected > 0) {
              let newListData = listData;
              newListData.push(value);

              setListData(newListData);
              setValue("");
            }
          },
          (err) => {
            console.log(err);
          }
        )
      })
    } else {
      Alert.alert('Info', 'Mohon masukkan data yang benar!')
    }
  }

Sedikit penjelasan, variable db yang sebelumnya sudah kita inisiasi di atas, sekarang kita gunakan untuk memulai transaction. Kemudian fungsi transaction mengembalikan callback function dengan prameter tx yang kita panggil untuk executeSql.

Dalam executeSql, kita memasukkan Insert Statement SQL dengan query binding. Setelah itu, dalam callback function success, kita tambahkan logic untuk memeriksa apakah berhasil insert dengan rowsAffected > 0.

Barulah kita taruh kembali setListData di dalam logic tersebut. Walaupun sudah masuk database, setelah kita keluar dari aplikasi dan masuk kembali, data yang ditampilkan tetap kosong, padahal kita sudah menambahkan data sebelumnya.

Data kembali kosong padahal SQLite telah berhasil terisi CodeSeem
Data Kosong padahal sudah diinsert.

Kenapa itu seperti mati? (Why is it like that?) Kalau temen-temen jeli, dalam map function di JSX, kita mengambil data dari variable listData. Padahal listData berasal dari useState dengan value kosong di awal. Maka tinggal kita tambahkan useEffect dengan argumen pertama sebuah function untuk fetch data dari SQLite dan argumen kedua sebuah array kosong [], supaya function bisa berjalan sekali ketika aplikasi dimuat.

Memodifikasi App.js supaya load data SQLite di awal

//Ganti line ini
import React, { useState } from 'react';

//dengan ini
import React, { useState, useEffect } from 'react';
//Tambahkan useEffect diatas return function
useEffect(() => {
    db.transaction((tx) => {
      tx.executeSql(
        'SELECT * FROM ms_user;',
        [],
        (txn, res) => {
          if (res.rows.length > 0) {
            let count = res.rows.length;
            let newListData = [];

            for (let index = 0; index < count; index++) {
              const element = res.rows.item(index);
              newListData.push(element.user_fullname);
            }

            setListData(newListData);
          }
        },
        (err) => {
          console.log(err);
        }
      )
    })
  }, []);

return (
...

Setelah temen-temen tambahkan useEffect, maka temen-temen akan mendapatkan hasil yang terisi di awal. Contohnya seperti di bawah ini.

Data sudah terload menggunakan useEffect dari SQLite CodeSeem
Data yang diload dari database

Sampai sini sebetulnya sudah selesai. Temen-temen bisa menambahkan data baru berdasarkan state dan juga update via SQLite. Hanya saja ada yang mau saya tambahkan. Temen-temen bisa lihat ada warning yang menunjukkan bahwa React menemukan dua element children dengan key yang sama. Ini terjadi karena pada map function, saya menggunakan value name sebagai key. Seperti di bawah ini.

listData.map(item => {
  return <Text key={item}>{item}</Text>
})

Padahal, di database kita memiliki column unique dengan auto-increment-nya. Column tersebut adalah user_id. Kita bisa memanfaatkan column tersebut sebagai key. Kita akan melakukan perubahan pada 3 tempat yakni, handleAddData, useEffect, dan map function. Perubahan tersebut adalah dengan merubah state listData yang tadinya menerima array of text, menjadi array of object. Sehingga object akan terlihat seperti dibawah ini.

{
  id: 1,
  name: 'John'
}

handleAddData

const handleAddData = () => {
    if (value) {
      db.transaction((tx) => {
        tx.executeSql(
          'INSERT INTO ms_user (user_fullname) VALUES (?);',
          [value],
          (txn, res) => {
            if (res.rowsAffected > 0) {
              let newListData = listData;
              let insertID = res.insertId;
              newListData.push({
                id: insertID, //memanfaatkan ID unique dari column user_id
                name: value
              });

              setListData(newListData);
              setValue("");
            }
          },
          (err) => {
            console.log(err);
          }
        )
      })
    } else {
      Alert.alert('Info', 'Mohon masukkan data yang benar!')
    }
  }

useEffect

useEffect(() => {
    db.transaction((tx) => {
      tx.executeSql(
        'SELECT * FROM ms_user;',
        [],
        (txn, res) => {
          if (res.rows.length > 0) {
            let count = res.rows.length;
            let newListData = [];

            for (let index = 0; index < count; index++) {
              const element = res.rows.item(index);
              newListData.push({
                id: element.user_id, //memanfaatkan value dari database, column user_id
                name: element.user_fullname //memanfaatkan value dari database, column user_fullname
              });
            }

            setListData(newListData);
          }
        },
        (err) => {
          console.log(err);
        }
      )
    })
  }, []);

map function

listData.map(item => {
  return <Text key={item.id}>{item.name}</Text>
})

Setelah kita rubah, tidak ada lagi warning karena seluruh element children memiliki key yang unique.

Ending

Baik temen-temen, kita telah mempelajari cara menggunakan sqlite react native Setelah ini, temen-temen bisa banyak explore tentang hal-hal yang berhubungan dengan SQLite seperti mungkin Update Statement, Delete Statement atau juga membuat View dan Table.

Semoga seluruh isi artikel ini bisa bermanfaat buat temen-temen. Kurang lebihnya mohon dimaafkan. Semoga kita selalu sehat dan diberikan keberkahan hidup. Aamiin.

Link github dibawah ini bous:
Github CodeSeem React Native SQLite

As always, i’ll show you a good quote.

“Jika aku belajar hanya untuk penghidupan, maka aku akan hidup.. namun jika aku belajar untuk mengamalkannya maka aku akan selalu hidup.”

― Hilaludin Wahid, seorang pecinta puisi Indonesia

Enjoy, keep learning…

Leave a Reply

Your email address will not be published. Required fields are marked *