Terakhir diperbarui: 2021-04-19
Penulis: Habibie Ed Dien, S.Kom., M.T.
Pada codelab ini Anda akan mempelajari tentang penggunaan Global API dan Hooks di ReactJS.
Sebelum memulai codelab ini, sebaiknya Anda memiliki pengetahuan dasar tentang:
Pada Codelab 5 kita pernah mempelajari tentang interaksi dengan API. Kita dihadapkan dengan mengelola banyak daftar alamat API yang disediakan dan mengumpulkannya menjadi satu kelompok. Sehingga kita dapat menambah, mengurangi, ataupun memperbaiki daftar API pada satu tempat.
Salah satu caranya adalah dengan mengelola/mengatur pemanggilan API secara GLOBAL, sehingga kita tidak perlu melakukan "coding ulang" API yang memiliki karakter yang sama. Contoh saat kita memanggil API (GET) untuk mendapatkan list Artikel, list komentar, dan list pengguna. API untuk ketiga proses tersebut sebenarnya sama, yang membedakan hanya alamat url API yang dituju, sehingga kita bisa meletakkan list API pada satu tempat untuk mempermudah dalam pengelolaannya.
Pada codelab ini, kita menggunakan materi dari Codelab 5 – API di ReactJS. Sehingga kita dapat memahami perbedaan antara Codelab 5 yang hanya melakukan interaksi satu API dengan codelab ini yang mengelola daftar list API ke dalam satu tempat, sehingga proses manajemen API lebih mudah dan cepat.
Terpusat. API yang dibuat atau yang akan dipanggil terpusat pada satu tempat.
Kustomisasi. Mudah dan efisien saat melakukan kustomisasi maupun perbaikan alamat API.
Mudah dikelola. Berhubung list API berada pada satu tempat, sehingga proses mengelola daftar API baik penambahan, pengurangan, maupun memperbaiki API (perubahan alamat API) bisa dilakukan dengan mudah.
Terhindar dari proses yang sama (redundansi). Berhubung daftar API dalam satu tempat sehingga kita bisa memantau dan meminimalisir proses yang sama atau pembuatan API yang sama persis.
Pada praktikum ini, dibagi menjadi beberapa bagian praktikum yaitu membuat global API untuk service GET, POST, Delete, dan manajemennya. Kita mulai dengan membuat global API untuk service GET sebagai berikut.
services
dalam folder src
, lalu buat file index.js
di dalam folder services
seperti pada gambar berikut.baseUrlApi
di src/services/index.js
sebagai alamat url utama API yang digunakan. Anda dapat mengaturnya secara terpusat di variabel baseUrlApi
ini.const baseUrlApi = 'http://localhost:3001';
GetAPI
untuk service GET.const GetAPI = (path) => {
const promise = new Promise((resolve, reject) => {
fetch(`${baseUrlApi}/${path}`)
.then(response => response.json())
.then((result) => {
resolve(result);
}, (err) => {
reject(err);
})
})
return promise;
}
getNewsBlog
untuk mendapatkan isi artikel. Dalam konstanta ini terdapat fungsi yang memanggil GetAPI
berisi parameter posts
yang diurutkan secara descending berdasarkan atribut id
.const getNewsBlog = () => GetAPI('posts?_sort=id&_order=desc');
const API = {
getNewsBlog
}
export default API;
src/components
dan isi file baru dengan nama BlogPost.js
.import React from 'react';
import API from '../services';
DaftarArtikel
di src/components/BlogPost.js
untuk menampilkan isi artikel.function DaftarArtikel(props){
return(
<div>
<h3>{props.judul}</h3>
<div>{props.isiArtikel}</div>
</div>
);
}
BlogPost
export default class BlogPost extends React.Component {
constructor(props){
super(props);
this.state = {
dataArtikel: [] // untuk menampung data API
};
}
ambilDataDariServerAPI = () => {
API.getNewsBlog().then(result => {
this.setState({
dataArtikel: result
})
})
}
componentDidMount () {
this.ambilDataDariServerAPI()
}
render(){
const { dataArtikel } = this.state;
return (
<div>
<h2>Daftar Artikel</h2>
{
dataArtikel.map(artikel => {
return <DaftarArtikel key={artikel.id} judul={artikel.title} isiArtikel={artikel.body} />
})
}
</div>
);
}
}
src/App.js
kita panggil class BlogPost
untuk dirender.import React from 'react';
import BlogPost from './components/BlogPost';
class App extends React.Component {
render () {
return (
<div>
<BlogPost />
</div>
);
}
}
export default App;
src/index.js
seperti biasa kita render.import ReactDOM from 'react-dom';
import App from './App.js';
ReactDOM.render(
<App />,
document.getElementById('root')
);
npm start
untuk melihat hasilnya di browser. Apa yang terjadi ? Apakah tampil data artikel tersebut ?listArtikel.json
di root project React kita.listArtikel.json
lalu isi datanya dengan copy dari https://jsonplaceholder.typicode.com/posts npm start
milik react tadi tetap running) dengan cara klik icon + seperti di gambar berikut.listArtikel.json
berada.json-server --watch listArtikel.json --port 3001
listArtikel.json
.src/services/index.js
dan tambahkan kode POST berikut ini.const PostAPI = (path, data) => {
const promise = new Promise((resolve, reject) => {
fetch(`${baseUrlApi}/${path}`, {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then((result) => {
resolve(result);
}, (err) => {
reject(err);
})
})
return promise;
}
postNewsBlog
untuk data yang dikirim.const postNewsBlog = (dataYgDikirim) => PostAPI('posts', dataYgDikirim);
src/components/BlogPost.js
tambahkan variabel postArtikel
untuk menampung data artikel yang akan dikirim melalui method POST.render()
kita tambahkan form untuk submit artikel seperti kode berikut.render () {
const { dataArtikel, postArtikel } = this.state;
return (
<div>
<div>
<form onSubmit={this.handleTombolSimpan}>
<label>
Judul Artikel:
<input type="text" name="title" defaultValue={postArtikel.title} onChange={this.handleOnChange} />
</label>
<label>
Isi Artikel:
<input type="text" name="body" defaultValue={postArtikel.body} onChange={this.handleOnChange} />
</label>
<input type="submit" value="Simpan" />
</form>
</div>
<hr></hr>
<h2>Daftar Artikel</h2>
{
dataArtikel.map(artikel => {
return <DaftarArtikel key={artikel.id} judul={artikel.title} isiArtikel={artikel.body} />
})
}
</div>
);
}
handleTombolSimpan
di dalam class BlogPost
.handleTombolSimpan = (e) => {
e.preventDefault();
API.postNewsBlog(this.state.postArtikel)
.then((response) => {
this.ambilDataDariServerAPI(); // refresh data
alert('Data berhasil disimpan!');
});
}
handleOnChange
handleOnChange = (e) => {
let name = e.target.name;
let value = e.target.value;
this.setState(prevState => {
prevState.postArtikel[name] = value;
return {
postArtikel: prevState.postArtikel
};
});
}
src/services/index.js
dan tambahkan kode DELETE berikut ini.const DeleteAPI = (path, data) => {
const promise = new Promise((resolve, reject) => {
fetch(`${baseUrlApi}/${path}/${data}`, { method: 'DELETE' })
.then((result) => {
resolve(result);
}, (err) => {
reject(err);
})
})
return promise;
}
deleteNewsBlog
untuk data yang dikirim.const deleteNewsBlog = (dataYgDihapus) => DeleteAPI('posts', dataYgDihapus);
src/components/BlogPost.js
bagian fungsi render()
tambahkan tombol Hapus
.<h2>Daftar Artikel</h2>
{
dataArtikel.map(artikel => {
return (
<div key={artikel.id}>
<DaftarArtikel judul={artikel.title} isiArtikel={artikel.body} />
<Button variant="danger" value={artikel.id} onClick={this.handleTombolHapus}>Hapus</Button>
<hr></hr>
</div>
)
})
}
handleTombolHapus
yang berisi kode berikut.handleTombolHapus = (e) => {
e.preventDefault();
API.deleteNewsBlog(e.target.value)
.then((response) => {
this.ambilDataDariServerAPI(); // refresh data
alert('Data berhasil dihapus!');
});
}
Pada global API yang telah kita lakukan pada praktikum di atas. Kita mengetahui bahwa saat kita benar-benar melakukan coding untuk membuat API, kita akan dihadapkan pada banyak URL API yang akan kita sediakan. Sehingga kita butuh mengelola Global API untuk lebih teratur.
Salah satu cara untuk mengelola Global API adalah dengan memisahkan API berdasarkan action-nya (GET, POST, DELETE). Sehingga jika terjadi error pada DELETE API, kita cukup akan membuka Global API bagian DELETE yang akan kita perbaiki.
Silakan lakukan langkah-langkah praktikum berikut ini.
src/services/API
dan src/services/Artikel
beserta file baru didalamnya seperti pada struktur di bawah ini.src/services/API/Config.js
adalah sebagai berikut. File Config.js
ini bisa menampung variabel global yang digunakan selama proses API.src/services/API/Get.js
adalah sebagai berikut.Post.js
dan Delete.js
isinya sesuai dengan praktikum sebelumnya, hanya saja dipindah di file terpisah. Silakan disesuaikan seperti pada file Get.js
!src/services/Artikel/index.js
berubah menjadi seperti berikut ini.import
pada bagian komponen BlogPost.js
dengan memanggil API pada bagian folder Artikel
.Buatlah folder baru di src/services/
Komentar
yang digunakan untuk mengelola data komentar. Buatlah komponen baru dengan nama Komentar.js
di folder components yang berfungsi untuk mengelola data komentar berdasarkan API yang telah dibuat!
Jangan lupa menambahkan objek di database json "comment
" untuk menampung data komentar. Atribut bisa terdiri dari userId
, nama
, komentar
, dan id
.
Hook dalam bahasa inggris jika diterjemahkan ke bahasa indonesia mempunyai arti "menghubungkan" atau "mengaitkan". Dalam bentuk plural hooks berarti banyak yang dihubungkan.
Hooks merupakan fungsi yang memungkinkan Anda untuk "mengaitkan" state dan fitur-fitur lifecycle React dari function component. Hooks tidak dapat berfungsi didalam kelas — Hooks memungkinkan menggunakan React tanpa kelas. (tidak direkomendasikan membuat ulang komponen yang sudah ada tetapi Anda dapat menggunakan Hooks untuk komponen yang baru jika diinginkan.)
Hooks merupakan fitur baru di React sejak versi 16.8. Dengan Hooks, kita dapat menggunakan state dan fitur React yang lain tanpa perlu menulis sebuah kelas baru. Perhatikan contoh kode di bawah ini.
import React, { useState } from 'react';
function ContohHook () {
// Mendeklarasikan variabel state baru, yaitu "count"
const [count, setCount] = useState(0);
return (
<div>
<p>Anda mengklik {count} kali</p>
<button onClick={() => setCount(count + 1)}>
Klik aku
</button>
</div>
);
}
export default ContohHook;
useState
adalah fungsi baru yang akan kita pelajari di sini. Kode diatas dapat merender tampilan counter dengan button yang bisa melalukan increment. Anda dapat mencobanya langsung pada aplikasi react Anda.
Sebelum kita melanjutkan, perlu diingat bahwa hooks itu:
Selain itu ada beberapa hal yang perlu diperhatikan terkait hooks, yaitu:
Fitur Class tidak akan dihapus dari React. Hadirnya fitur hooks bukan berarti menggantikan fitur class yang telah Anda pelajari sebelumnya. Untuk strategi penggunaan hooks secara bertahap, dapat dibaca pada link ini.
Hooks tidak akan menggantikan pengetahuan tentang konsep React yang telah Anda pelajari. Justru fitur Hooks menyediakan akses langsung API ke konsep React yang sudah dipelajari seperti props, state, context, refs, dan lifecycle.
Untuk mempelajari lebih lanjut tentang Hooks dapat membaca di sini.
Beberapa permasalahan yang dihadapi sebelum hadirnya fitur hooks adalah sebagai berikut.
Sulitnya menggunakan kembali stateful logic antar komponen
Selamat, Anda telah berhasil menyelesaikan codelab ini. Semoga mendapatkan ilmu yang bermanfaat.
Silakan cek beberapa sumber belajar lainnya...