React JS (Pengenalan)

ReactJS merupakan sebuah library dari facebook yang dapat digunakan untuk membangun antarmuka pengguna. Pada bagian ini kita akan mencoba menggunakan React untuk membangun aplikasi sederhana, untuk melihat konsep-konsep inti yang ditawarkan oleh React.

Sebelum mulai mencoba menggunakan React, beberapa prasyarat yang diperlukan yaitu:

  1. React Starter Kit untuk berbagai file dari React
  2. jQuery, sebagai library pendukung

Jika sudah mengambil kedua kebutuhan di atas, ekstrak React Starter Kit ke dalam sebuah direktori dan jalankan sebuah web server lokal (misal: http-server) di dalamnya. Seluruh eksperimen kita akan dijalankan dari direktori ini.

Hello, React!

Untuk memulai eksperimen, kita akan langsung mencoba membuat sebuah halaman sederhana dengan menggunakan ReactJS. Buat sebuah file dengan nama index.html di dalam direktori utama starter kit ReactJS, dan isikan dengan kode berikut:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html>
    <head>
        <script src="build/react.js"></script>
        <script src="build/JSXTransformer.js"></script>
    </head>
    <body>
        <div id="content"></div>
        <script type="text/jsx">
            React.render(
                <h1>Hello, world!</h1>,
                document.getElementById('content')
            );
        </script>
    </body>
</html>

Buka index.html pada browser dan lihat hasil eksekusinya.

_images/1-hello-world.png

Apa yang baru saja kita lakukan?

Pada bagian <head> dari index.html kita memasukkan semua modul Javascript yang dibutuhkan oleh ReactJS. <div id="content"> merupakan elemen yang akan menampung antarmuka yang kita hasilkan dengan menggunakan ReactJS. React.render merupakan fungsi utama dari ReactJS, yang akan menggambarkan antarmuka yang kita buat. Fungsi ini menerima dua buah argumen:

  1. Argumen pertama merupakan bentuk dari keluaran antarmuka yang ingin kita buat. Perhatikan bagaimana kita menggunakan sintaks yang mirip dengan HTML di sini. Kode <h1>Hello, world!</h1> yang kita isikan bukan HTML, melainkan sebuah sintaks khusus yang bernama JSX. Perhatikan juga bahwa kita menggunakan <script type="text/jsx"> pada awal tag <script>. Penjelasan lebih lanjut mengenai JSX akan kita tambahkan nanti.
  2. Parameter kedua menerima elemen DOM tempat kita ingin menampilkan keluaran dari elemen pertama. Parameter ini cukup gamblang, dan kita hanya mengirimkan elemen DOM standar yang didapat dari document.getElementById di sini.

Bentuk awal dari penggunaan ReactJS memang cukup sederhana. Kita akan melihat bagaimana hampir keseluruhan pengembangan dari ReactJS berdasar dari model sederhana ini nantinya.

Kode ReactJS pada File Terpisah

Jika diinginkan, kita juga dapat memisahkan kode JSX kita pada sebuah file terpisah, layaknya kita memisahkan kode javascript biasa pada file lain. Misalnya, kita dapat membuat sebuah file src/helloworld.js dengan isi:

1
2
3
4
React.render(
    <h1>Hello, world!</h1>,
    document.getElementById('content')
);

Dan tentunya kita harus menggantikan tag script pada index.html menjadi:

1
<script type="text/jsx" src="src/helloworld.js"></script>

Dapat dilihat bagaimana tidak terdapat perbedaan mencolok antara penggunaan javascript dengan JSX, selain pada bagian di mana JSX dapat menerima kode yang mirip HTML di dalamnya.

Kompilasi JSX ke Javascript

Jika ingin, kita dapat juga melakukan kompilasi JSX ke javascript, yang pada kode sebelumnya dilakukan oleh JSXTransformer.js secara otomatis dan langsung. Kompilasi tentunya akan menghemat waktu eksekusi kode, karena browser dapat langsung membaca kode javascript yang kita berikan tanpa perlu melakukan transformasi dari JSX ke javascript lagi. Kompilasi dari JSX ke javascript dapat dilakukan dengan menggunakan tools yang telah disediakan ReactJS, melalui platform NodeJS.

Untuk dapat melakukan kompilasi, pertama-tama kita harus melakukan instalasi tools:

1
npm install -g react-tools

Kita kemudian dapat mengubah src/hellworld.js yang berisi JSX menjadi javascript dengan perintah:

1
jsx --watch src/ out/

Tentunya karena kita telah memiliki hasil kompilasi JSX, kita tidak lagi perlu menggunakan JSXTransformer.js pada HTML kita, dan kita juga dapat langsung memasukkan hasil kompilasi seperti berikut:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<!DOCTYPE html>
<html>
    <head>
        <script src="build/react.js"></script>
        <!-- Tidak ada lagi JSXTransformer.js -->
    </head>
    <body>
        <div id="content"></div>
        <script src="out/helloworld.js"></script>
    </body>
</html>

Perhatikan juga bagaimana kita tidak lagi memasukkan type="text/jsx" pada tag <script>. Isi dari out/helloworld.js sendiri adalah seperti berikut:

1
2
3
4
React.render(
    React.createElement('h1', null, 'Hello, world!'),
    document.getElementById('content')
);

Dengan hanya perbedaan pada bagian sintaks JSX saja. Tentunya kita juga dapat langsung menggunakan pemanggilan fungsi seperti yang ada pada file hasil kompilasi ini jika mau.

Pembangunan Elemen Antarmuka ReactJS

ReactJS merupaakn sebuah library yang berbasis komponen. Hal ini menyebabkan kita harus mengembangkan sebuah elemen antarmuka komponen demi komponen. Kita akan langsung melihat bagaimana kita dapat mengembangkan sebuah komponen ReactJS sederhana dengan menggunakan fungsi-fungsi yang ada.

Aplikasi percobaan yang akan kita bangun adalah sebuah todo list (TDL) sederhana, yang menyimpan catatan berbagai hal yang akan kita lakukan. Tampilan aplikasi sangat sederhana:

_images/2-todolist-fin.png

TDL yang akan kita kembangkan ini akan terdiri dari tiga buah komponen, yaitu

  1. komponen yang menerima masukan pengguna untuk menambahkan data baru,
  2. komponen yang menampilkan semua tugas pengguna yang telah tercatat dalam sistem, dan
  3. komponen utama TDL yang menampung kedua komponen sebelumnya.

Jika diilustrasikan, pembagian komponen kita dapat dilihat seperti gambar berikut:

_images/3-todolist-comp.png

Langsung saja, kita dapat mulai membangun elemen antarmuka TDL ini dari file HTML yang diperlukan. Buat sebuah file todo.html dan isikan dengan kode berikut:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Todolist React</title>
</head>
<body>
    <div id="content"></div>

    <script src="build/react.js"></script>
    <script src="build/JSXtransformer.js"></script>

    <script type="text/jsx" src="src/todolist.js"></script>
</body>
</html>

HTML yang dibuat cukup standar. Sekarang kita akan membuat file javascript yang dibutuhkan, yaitu src/todolist.js:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
var TodoForm = React.createClass({
    render: function () {
        return (
            <div className="todoForm">
                <label htmlFor="todoInput">
                    Tambahkan Data:
                </label>
                <input type="text" id="todoInput" className="inputForm" />
            </div>
        );
    }
});

React.render(
    <TodoForm />,
    document.getElementById("content")
);

Jalankan kode dan lihat apa yang kita dapatkan:

_images/4-todolist-form.png

Apa yang baru saja terjadi?

Pertama, kita membuat sebuah komponen baru di dalam ReactJS dengan menggunakan method React.createClass. Method ini menerima sebuah parameter berupa objek yang dapat memiliki banyak method. Untuk contoh awal ini, kita hanya mengirimkan satu buah method: render. render merupakan method yang mengembalikan komponen React yang nantinya akan diubah menjadi HTML.

Elemen <div className="todoForm"> yang kita kembalikan bukan merupakan elemen DOM murni yang dikenali langsung oleh browser. Sebagai kode JSX, kita dapat menganggap elemen ini merupakan elemen DOM khusus milik React, yang nantinya akan diterjemahkan menjadi HTML. Perhatikan bagaimana untuk menambahkan kelas pada elemen kita menggunakan atribut className, bukan class seperti pada HTML standar. Hasil kembalian fungsi ini akan diubah menjadi HTML oleh React.render pada waktunya, dan hasil keluaran HTML ini relatif aman. React tidak menghasilkan string HTML sehingga kita terlindungi dari serangan XSS.

Setiap kali kita telah membuat komponen baru melalui React.createClass, kita kemudian dapat menyimpan komponen ini ke dalam sebuah variabel. Nama dari variabel ini kemudian akan menjadi komponen baru dari React, yang dapat digunakan sebagai markup buatan sendiri dalam JSX. Karena hal ini lah kita dapat langsung mengirimkan komponen yang baru kita buat sebagai <TodoForm /> ke React.render. Kita bahkan dapat menggunakan <TodoForm /> di dalam nilai kembalian komponen lainnya.

Untuk mengirimkan data ke dalam komponen React, kita juga dapat menambahkan atribut ke dalam elemen yang baru saja kita buat. Atribut ini dapat diisikan dengan nama apapun, selama tidak bertabrakan dengan atribut standar HTML. Pengisian atribut ke dalam elemen dilakukan dengan mengguankan pemisah {}, seperti berikut:

1
2
3
4
5
6
var judul = "Tambahkan Data";

React.render(
    <TodoForm teks={judul} />,
    document.getElementById("content")
);

Kita kemudian dapat mengakses nilai atribut ini dengan menggunakan properti props pada objek yang dikirimkan ke React.createClass:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
var TodoForm = React.createClass({
    render: function () {
        return (
            <div className="todoForm">
                <label htmlFor="todoInput">
                    { this.props.teks }
                </label>
                <input type="text" id="todoInput" className="inputForm" />
            </div>
        );
    }
});

Penggabungan beberapa komponen dalam React juga dilakukan dengan cukup natural: hanya dengan menggunakan komponen-komponen yang telah kita kembangkan layaknya sebuah tag HTML biasa. Pertama, mari kita buat komponen baru untuk menampung semua data yang ada:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// data boleh berasal dari mana saja.
// asumsikan data sudah didapatkan.
var data = [
    {content: "Beli Telur", tag: "belanja"},
    {content: "Tugas Javascript", tag: "kuliah"},
    {content: "This War of Mine", tag: "game"},
    {content: "Doraemon", tag: "film"}
];

var List = React.createClass({
    render: function () {
        var listData = this.props.data.map(function (data) {
            return (
                <li>{data.content}, tag: {data.tag}</li>
            );
        });

        return (
            <ul className="list">
                {listData}
            </ul>
        );
    }
});

Elemen List yang kita kembangkan melakukan sesuatu yang menarik. Data yang kita peroleh, berupa array dari objek, dipetakan menjadi array dari elemen <li> JSX pada variabel listData. listData kemudian langsung kita masukkan sebagai nilai literal di dalam <ul> yang dikembalikan, dan React secara otomatis mengetahui apa yang harus dilakukan dengan array <li>!

Penggabungan List dan TodoForm dapat dilakukan dengan cukup alami:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
var TodoList = React.createClass({
    render: function () {
        return (
            <div className="TodoList">
                <h1>Todo List</h1>
                <TodoForm teks="Tambahkan Data : " />
                <List data={this.props.data} />
            </div>
        );
    }
});

React.render(
    <TodoList data={data} />,
    document.getElementById("content")
);

Perlu dicatat bahwa sebuah elemen yang dikembalikan oleh komponen React hanya boleh terdiri dari satu elemen terluar. Hal ini berarti kode berikut:

1
2
3
4
5
6
7
8
var TodoList = React.createClass({
    render: function () {
        return (
            <TodoForm teks="Tambahkan Data : " />
            <List data={this.props.data} />
        );
    }
});

Tidak akan dapat berjalan dan memberikan kesalahan kompilasi. Untuk menanggulangi hal ini pastikan untuk selalu membuat elemen pembungkus agar hanya terdapat satu elemen terluar saja.

Mengambil Data Dari Server

Aplikasi web umumnya tentunya tidak menyimpan data di dalam array secara lokal seperti contoh pada bagian sebelumnya. Yang biasanya terjadi adalah pengambilan data dilakukan melalui sisi server. Untuk dapat melakukan hal ini, kita akan melakukan dua hal. Pertama, pada todo.html kita akan menambahkan jQuery:

1
2
3
4
5
<head>
    <script src="build/jquery-2.1.1.min.js"></script>
    <script src="build/react.js"></script>
    <script src="build/JSXTransformer.js"></script>
</head>

Kita kemudian perlu membuat file data.json yang isinya tidak berbeda jauh dengan variabel data yang kita buat sebelumnya:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
[
    {
        "content": "Beli Telur",
        "tag": "belanja"
    },
    {
        "content": "Tugas Javascript",
        "tag": "kuliah"
    },
    {
        "content": "This War of Mine",
        "tag": "game"
    },
    {
        "content": "Doraemon",
        "tag": "film"
    }
]

Data pada data.json ini nantinya yang akan kita ambil dari sever. Selanjutnya, kita tidak akan langsung menggunakan variabel data lagi untuk mengisikan list. Kita akan mengirimkan URL data yang diperlukan saja.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
var TodoList = React.createClass({
    render: function () {
        return (
            <div className="TodoList">
                <h1>Todo List</h1>
                <TodoForm teks="Tambahkan Data : " />
                <List url={this.props.url} />
            </div>
        );
    }
});

React.render(
    <TodoList url="./data.json" />,
    document.getElementById("content")
);

Selanjutnya, kita perlu memperbaharui komponen List seperti berikut:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
var List = React.createClass({
    loadData: function () {
        $.ajax({
            url: this.props.url,
            dataType: 'json',
            success: function (data) {
                this.setState({data: data})
            }.bind(this),
            error: function (xhr, status, err) {
                console.log(xhr);
                console.log(status);
                console.log(err);
            }.bind(this)
        });
    },
    getInitialState: function () {
        return { data: [] }
    },
    componentDidMount: function () {
        this.loadData();
    },
    render: function () {
        var listData = this.state.data.map(function (data) {
            return (
                <li>{data.content}, tag: {data.tag}</li>
            );
        });

        return (
            <ul className="list">
                {listData}
            </ul>
        );
    }
});

Terdapat beberapa method tambahan yang digunakan di sini. Pertama, method loadData merupakan method buatan kita untuk mengambil data dari server. loadData cukup sederhana, hanya melakukan pengambilan data melalui fungsi $.ajax dari jQuery.

Pada aplikasi kita sejauh ini, setiap komponen yang kita kembangkan menampilkan dirinya berdasarkan props yang kita kirimkan. Nilai props tidak dapat berubah isinya. props dikirimkan oleh komponen teratas, dan “dimiliki” oleh komponen tersebut. Karena hanya dikirimkan kepada objek, maka nilai props tidak dapat diubah. Jika ingin mengubah data untuk mendapatkan interaktifitas aplikasi, kita perlu menggunakan mekanisme khusus yang disediakan React. this.state merupakan komponen privat yang dapat diganti isinya dengan memanggil this.setState. Ketika nilai state diperbaharui, komponen React akan secara otomatis diperbaharui juga (fungsi render dipanggil kembali).

Fungsi render sendiri dituliskan sebagai fungsi deklaratif milik this.props dan this.state. Hal ini menjadikan komponen antarmuka selalu konsisten dengan interaksi pengguna.

Data dari this.state sendiri kita inisialisasi melalui fungsi getInitialState. Nilai yang dikembalikan getInitialState akan menjadi nilai awal dari this.state. Fungsi ini dijamin oleh React hanya akan berjalan sekali selama masa hidup komponen.

Method componentDidMount dipanggil secara otomatis oleh React ketika komponen digambarkan. Kita memanggil this.setState di sini agar data diperbaharui secara dinamis. Array data yang lama kita gantikan dengan data yang diambil dari server, dan komponen (UI) akan secara otomatis memperbaharui dirinya sendiri. Karena ini, kita dapat dengan mudah mengimplementasikan live update, dengan teknik polling:

1
2
3
4
componentDidMount: function () {
    this.loadData();
    setInterval(this.loadData, 2000);
},

Tentu saja kita dapat mengimplementasikan metode live update yang lebih baik, misalnya dengan menggunakan WebSocket di bagian ini.

comments powered by Disqus
Kembali ke bertzzie.com