Memahami GraphQl Sisi Klien Dengan Apollo-Client Dalam Aplikasi Bereaksi
Diterbitkan: 2022-03-10Menurut State of JavaScript 2019, 38,7% pengembang ingin menggunakan GraphQL, sementara 50,8% pengembang ingin mempelajari GraphQL.
Menjadi bahasa query, GraphQL menyederhanakan alur kerja membangun aplikasi klien. Ini menghilangkan kerumitan pengelolaan titik akhir API di aplikasi sisi klien karena memperlihatkan titik akhir HTTP tunggal untuk mengambil data yang diperlukan. Oleh karena itu, ini menghilangkan pengambilan data yang berlebihan dan pengambilan data yang kurang, seperti dalam kasus REST.
Tapi GraphQL hanyalah bahasa query. Untuk menggunakannya dengan mudah, kami membutuhkan platform yang melakukan angkat berat untuk kami. Salah satu platform tersebut adalah Apollo.
Platform Apollo adalah implementasi GraphQL yang mentransfer data antara cloud (server) ke UI aplikasi Anda. Saat Anda menggunakan Apollo Client, semua logika untuk mengambil data, melacak, memuat, dan memperbarui UI dienkapsulasi oleh kait useQuery
(seperti dalam kasus React). Oleh karena itu, pengambilan data bersifat deklaratif. Ini juga memiliki cache konfigurasi nol. Hanya dengan menyiapkan Apollo Client di aplikasi Anda, Anda mendapatkan cache cerdas di luar kotak, tanpa memerlukan konfigurasi tambahan.
Apollo Client juga dapat dioperasikan dengan kerangka kerja lain, seperti Angular, Vue.js, dan React.
Catatan : Tutorial ini akan bermanfaat bagi mereka yang pernah bekerja dengan RESTful atau bentuk lain dari API di masa lalu di sisi klien dan ingin melihat apakah GraphQL layak untuk dicoba. Ini berarti Anda seharusnya pernah bekerja dengan API sebelumnya; hanya dengan begitu Anda akan dapat memahami betapa bermanfaatnya GraphQL bagi Anda. Sementara kita akan membahas beberapa dasar GraphQL dan Apollo Client, pengetahuan yang baik tentang JavaScript dan React Hooks akan berguna.
Dasar-dasar GraphQL
Artikel ini bukan pengantar lengkap untuk GraphQL, tetapi kami akan mendefinisikan beberapa konvensi sebelum melanjutkan.
Apa itu GraphQL?
GraphQL adalah spesifikasi yang menjelaskan bahasa kueri deklaratif yang dapat digunakan klien Anda untuk meminta API untuk data persis yang mereka inginkan. Ini dicapai dengan membuat skema tipe yang kuat untuk API Anda, dengan fleksibilitas tertinggi. Ini juga memastikan bahwa API menyelesaikan data dan kueri klien divalidasi terhadap skema. Definisi ini berarti bahwa GraphQL berisi beberapa spesifikasi yang menjadikannya bahasa kueri deklaratif, dengan API yang diketik secara statis (dibangun di sekitar TypeScript) dan memungkinkan klien untuk memanfaatkan sistem tipe tersebut untuk meminta API untuk data persis yang diinginkannya. .
Jadi, jika kami membuat beberapa tipe dengan beberapa bidang di dalamnya, maka, dari sisi klien, kami dapat mengatakan, "Beri kami data ini dengan bidang yang sama persis ini". Kemudian API akan merespons dengan bentuk yang tepat, sama seperti jika kita menggunakan sistem tipe dalam bahasa yang diketik dengan kuat. Anda dapat mempelajari lebih lanjut di artikel TypeScript saya.
Mari kita lihat beberapa konvensi GraphQl yang akan membantu kita saat kita melanjutkan.
Dasar
- Operasi
Di GraphQL, setiap tindakan yang dilakukan disebut operasi. Ada beberapa operasi, yaitu:- Pertanyaan
Operasi ini berkaitan dengan pengambilan data dari server. Anda juga bisa menyebutnya pengambilan hanya-baca. - Mutasi
Operasi ini melibatkan pembuatan, pembaruan, dan penghapusan data dari server. Ini secara populer disebut operasi CUD (buat, perbarui, dan hapus). - Langganan
Operasi ini di GraphQL melibatkan pengiriman data dari server ke kliennya ketika peristiwa tertentu terjadi. Mereka biasanya diimplementasikan dengan WebSockets.
- Pertanyaan
Pada artikel ini, kita hanya akan berurusan dengan operasi query dan mutasi.
- Nama operasi
Ada nama unik untuk kueri sisi klien dan operasi mutasi Anda. - Variabel dan argumen
Operasi dapat mendefinisikan argumen, sangat mirip dengan fungsi di sebagian besar bahasa pemrograman. Variabel-variabel tersebut kemudian dapat diteruskan ke panggilan kueri atau mutasi di dalam operasi sebagai argumen. Variabel diharapkan diberikan saat runtime selama eksekusi operasi dari klien Anda. - Alias
Ini adalah konvensi di GraphQL sisi klien yang melibatkan penggantian nama verbose atau nama bidang yang tidak jelas dengan nama bidang yang sederhana dan dapat dibaca untuk UI. Aliasing diperlukan dalam kasus penggunaan di mana Anda tidak ingin memiliki nama bidang yang saling bertentangan.
Apa itu GraphQL Sisi Klien?
Ketika seorang insinyur front-end membangun komponen UI menggunakan kerangka kerja apa pun, seperti Vue.js atau (dalam kasus kami) React, komponen tersebut dimodelkan dan dirancang dari pola tertentu pada klien agar sesuai dengan data yang akan diambil dari server.
Salah satu masalah paling umum dengan RESTful API adalah overfetching dan underfetching. Ini terjadi karena satu-satunya cara bagi klien untuk mengunduh data adalah dengan mencapai titik akhir yang mengembalikan struktur data tetap . Overfetching dalam konteks ini berarti bahwa klien mengunduh lebih banyak informasi daripada yang dibutuhkan oleh aplikasi.
Di GraphQL, di sisi lain, Anda cukup mengirim satu kueri ke server GraphQL yang menyertakan data yang diperlukan. Server kemudian akan merespons dengan objek JSON dari data persis yang Anda minta — karenanya, tidak ada pengambilan yang berlebihan. Sebastian Eschweiler menjelaskan perbedaan antara RESTful API dan GraphQL.
GraphQL sisi klien adalah infrastruktur sisi klien yang berinteraksi dengan data dari server GraphQL untuk melakukan fungsi berikut:
- Ini mengelola data dengan mengirimkan kueri dan mengubah data tanpa Anda harus membuat permintaan HTTP sendirian. Anda dapat menghabiskan lebih sedikit waktu untuk data pipa dan lebih banyak waktu membangun aplikasi yang sebenarnya.
- Ini mengelola kompleksitas cache untuk Anda. Jadi, Anda dapat menyimpan dan mengambil data yang diambil dari server, tanpa campur tangan pihak ketiga, dan dengan mudah menghindari pengambilan ulang sumber daya duplikat. Dengan demikian, ini mengidentifikasi ketika dua sumber daya adalah sama, yang sangat bagus untuk aplikasi yang kompleks.
- Itu membuat UI Anda konsisten dengan UI Optimis, sebuah konvensi yang mensimulasikan hasil mutasi (yaitu data yang dibuat) dan memperbarui UI bahkan sebelum menerima respons dari server. Setelah respon diterima dari server, hasil optimis dibuang dan diganti dengan hasil yang sebenarnya.
Untuk informasi lebih lanjut tentang GraphQL sisi klien, luangkan waktu satu jam dengan cocreator GraphQL dan orang-orang keren lainnya di GraphQL Radio.
Apa itu Klien Apollo?
Apollo Client adalah klien GraphQL yang dapat dioperasikan, sangat fleksibel, berbasis komunitas untuk JavaScript dan platform asli. Fitur-fiturnya yang mengesankan termasuk alat manajemen negara yang kuat (Apollo Link), sistem caching tanpa konfigurasi, pendekatan deklaratif untuk mengambil data, pagination yang mudah diterapkan, dan UI Optimis untuk aplikasi sisi klien Anda.
Klien Apollo tidak hanya menyimpan status dari data yang diambil dari server, tetapi juga status yang dibuat secara lokal di klien Anda; karenanya, ia mengelola status untuk data API dan data lokal.
Penting juga untuk dicatat bahwa Anda dapat menggunakan Apollo Client bersama alat manajemen negara lainnya, seperti Redux, tanpa konflik. Selain itu, dimungkinkan untuk memigrasikan manajemen status Anda dari, katakanlah, Redux ke Klien Apollo (yang berada di luar cakupan artikel ini). Pada akhirnya, tujuan utama Klien Apollo adalah untuk memungkinkan para insinyur melakukan kueri data dalam API dengan mulus.
Fitur Klien Apollo
Klien Apollo telah memenangkan begitu banyak insinyur dan perusahaan karena fitur-fiturnya yang sangat membantu yang membuat pembuatan aplikasi modern yang kuat menjadi mudah. Fitur-fitur berikut datang dipanggang:
- Cache
Apollo Client mendukung caching dengan cepat. - UI Optimis
Klien Apollo memiliki dukungan keren untuk UI Optimis. Ini melibatkan sementara menampilkan keadaan akhir dari suatu operasi (mutasi) saat operasi sedang berlangsung. Setelah operasi selesai, data nyata menggantikan data optimis. - paginasi
Apollo Client memiliki fungsionalitas bawaan yang membuatnya cukup mudah untuk mengimplementasikan pagination dalam aplikasi Anda. Ini menangani sebagian besar sakit kepala teknis dalam mengambil daftar data, baik dalam tambalan atau sekaligus, menggunakan fungsifetchMore
, yang disertakan dengan kaituseQuery
.
Pada artikel ini, kita akan melihat pilihan fitur-fitur ini.
Cukup teorinya. Kencangkan sabuk pengaman Anda dan ambil secangkir kopi untuk menemani pancake Anda, karena tangan kita akan kotor.
Membangun Aplikasi Web Kami
Proyek ini terinspirasi oleh Scott Moss.
Kami akan membangun aplikasi web toko hewan peliharaan sederhana, yang fitur-fiturnya meliputi:
- mengambil hewan peliharaan kita dari sisi server;
- membuat hewan peliharaan (yang melibatkan pembuatan nama, jenis hewan peliharaan, dan gambar);
- menggunakan UI Optimis;
- menggunakan pagination untuk mengelompokkan data kita.
Untuk memulai, kloning repositori, pastikan bahwa cabang starter
adalah yang telah Anda kloning.
Mulai
- Instal ekstensi Alat Pengembang Klien Apollo untuk Chrome.
- Menggunakan antarmuka baris perintah (CLI), navigasikan ke direktori repositori yang dikloning, dan jalankan perintah untuk mendapatkan semua dependensi:
npm install
. - Jalankan perintah
npm run app
untuk memulai aplikasi. - Saat masih di folder root, jalankan perintah
npm run server
. Ini akan memulai server back-end kami untuk kami, yang akan kami gunakan saat kami melanjutkan.
Aplikasi harus terbuka di port yang dikonfigurasi. Milik saya adalah https://localhost:1234/
; milikmu mungkin sesuatu yang lain.
Jika semuanya bekerja dengan baik, aplikasi Anda akan terlihat seperti ini:
Anda akan melihat bahwa kami tidak memiliki hewan peliharaan untuk ditampilkan. Itu karena kami belum membuat fungsionalitas seperti itu.
Jika Anda telah menginstal Alat Pengembang Klien Apollo dengan benar, buka alat pengembang dan klik ikon baki. Anda akan melihat "Apollo" dan sesuatu seperti ini:
Seperti alat pengembang Redux dan React, kami akan menggunakan Alat Pengembang Klien Apollo untuk menulis dan menguji kueri dan mutasi kami. Ekstensi hadir dengan GraphQL Playground.
Mengambil Hewan Peliharaan
Mari tambahkan fungsionalitas yang mengambil hewan peliharaan. Pindah ke client/src/client.js
. Kami akan menulis Klien Apollo, menautkannya ke API, mengekspornya sebagai klien default, dan menulis kueri baru.
Copy kode berikut dan paste di client.js
:
import { ApolloClient } from 'apollo-client' import { InMemoryCache } from 'apollo-cache-inmemory' import { HttpLink } from 'apollo-link-http' const link = new HttpLink({ uri: 'https://localhost:4000/' }) const cache = new InMemoryCache() const client = new ApolloClient({ link, cache }) export default client
Berikut penjelasan dari apa yang terjadi di atas:
-
ApolloClient
Ini akan menjadi fungsi yang membungkus aplikasi kita dan, dengan demikian, berinteraksi dengan HTTP, menyimpan data, dan memperbarui UI. -
InMemoryCache
Ini adalah penyimpanan data yang dinormalisasi di Apollo Client yang membantu memanipulasi cache di aplikasi kami. -
HttpLink
Ini adalah antarmuka jaringan standar untuk memodifikasi aliran kontrol permintaan GraphQL dan mengambil hasil GraphQL. Ini bertindak sebagai middleware, mengambil hasil dari server GraphQL setiap kali tautan diaktifkan. Plus, ini adalah pengganti yang baik untuk opsi lain, sepertiAxios
danwindow.fetch
. - Kami mendeklarasikan variabel tautan yang ditetapkan ke instance
HttpLink
. Dibutuhkan propertiuri
dan nilai ke server kami, yaituhttps://localhost:4000/
. - Berikutnya adalah variabel cache yang menyimpan instance baru
InMemoryCache
. - Variabel klien juga mengambil contoh
ApolloClient
dan membungkuslink
dancache
. - Terakhir, kami mengekspor
client
sehingga kami dapat menggunakannya di seluruh aplikasi.
Sebelum kita melihat ini beraksi, kita harus memastikan bahwa seluruh aplikasi kita terekspos ke Apollo dan bahwa aplikasi kita dapat menerima data yang diambil dari server dan dapat mengubah data itu.
Untuk mencapai ini, mari menuju ke client/src/index.js
:
import React from 'react' import ReactDOM from 'react-dom' import { BrowserRouter } from 'react-router-dom' import { ApolloProvider } from '@apollo/react-hooks' import App from './components/App' import client from './client' import './index.css' const Root = () => ( <BrowserRouter>
<ApolloProvider client={client}> <App /> </ApolloProvider>
</BrowserRouter> ); ReactDOM.render(<Root />, document.getElementById('app')) if (module.hot) { module.hot.accept() }
Seperti yang akan Anda lihat dalam kode yang disorot, kami telah membungkus komponen App
di ApolloProvider
dan meneruskan klien sebagai prop ke client
. ApolloProvider
mirip dengan Context.Provider
React. Ini membungkus aplikasi React Anda dan menempatkan klien dalam konteks, yang memungkinkan Anda untuk mengaksesnya dari mana saja di pohon komponen Anda.
Untuk mengambil hewan peliharaan kita dari server, kita perlu menulis kueri yang meminta bidang persis yang kita inginkan. client/src/pages/Pets.js
, dan salin dan tempel kode berikut ke dalamnya:
import React, {useState} from 'react' import gql from 'graphql-tag' import { useQuery, useMutation } from '@apollo/react-hooks' import PetsList from '../components/PetsList' import NewPetModal from '../components/NewPetModal' import Loader from '../components/Loader'
const GET_PETS = gql` query getPets { pets { id name type img } } `;
export default function Pets () { const [modal, setModal] = useState(false)
const { loading, error, data } = useQuery(GET_PETS); if (loading) return <Loader />; if (error) return <p>An error occured!</p>;
const onSubmit = input => { setModal(false) } if (modal) { return <NewPetModal onSubmit={onSubmit} onCancel={() => setModal(false)} /> } return ( <div className="page pets-page"> <section> <div className="row betwee-xs middle-xs"> <div className="col-xs-10"> <h1>Pets</h1> </div> <div className="col-xs-2"> <button onClick={() => setModal(true)}>new pet</button> </div> </div> </section> <section>
<PetsList pets={data.pets}/>
</section> </div> ) }
Dengan beberapa bit kode, kami dapat mengambil hewan peliharaan dari server.
Apa itu gql?
Penting untuk dicatat bahwa operasi di GraphQL umumnya adalah objek JSON yang ditulis dengan graphql-tag
dan dengan backticks.
tag gql
adalah tag literal template JavaScript yang mengurai string kueri GraphQL ke dalam GraphQL AST (pohon sintaksis abstrak).
- Operasi kueri
Untuk mengambil hewan peliharaan kita dari server, kita perlu melakukan operasi kueri.- Karena kami membuat operasi
query
, kami perlu menentukantype
operasi sebelum menamainya. - Nama kueri kami adalah
GET_PETS
. Ini adalah konvensi penamaan GraphQL untuk menggunakan camelCase untuk nama bidang. - Nama ladang kami adalah
pets
. Oleh karena itu, kami menentukan bidang yang tepat yang kami butuhkan dari server(id, name, type, img)
. -
useQuery
adalah kait React yang merupakan dasar untuk mengeksekusi kueri dalam aplikasi Apollo. Untuk melakukan operasi kueri di komponen React kami, kami memanggil hookuseQuery
, yang awalnya diimpor dari@apollo/react-hooks
. Selanjutnya, kami memberikan string kueri GraphQL, yaituGET_PETS
dalam kasus kami.
- Karena kami membuat operasi
- Saat komponen kami dirender,
useQuery
mengembalikan respons objek dari Apollo Client yang berisi properti pemuatan, kesalahan, dan data. Dengan demikian, mereka dirusak, sehingga kita dapat menggunakannya untuk merender UI. -
useQuery
luar biasa. Kami tidak harus menyertakanasync-await
. Itu sudah diurus di latar belakang. Cukup keren, bukan?-
loading
Properti ini membantu kami menangani status pemuatan aplikasi. Dalam kasus kami, kami mengembalikan komponenLoader
saat aplikasi kami dimuat. Secara default, pemuatan adalahfalse
. -
error
Untuk berjaga-jaga, kami menggunakan properti ini untuk menangani kesalahan apa pun yang mungkin terjadi. -
data
Ini berisi data aktual kami dari server. - Terakhir, dalam komponen
PetsList
kita, kita melewatkan propspets
, dengandata.pets
sebagai nilai objek.
-
Pada titik ini, kami telah berhasil menanyakan server kami.
Untuk memulai aplikasi kita, mari kita jalankan perintah berikut:
- Mulai aplikasi klien. Jalankan perintah
npm run app
di CLI Anda. - Mulai server. Jalankan perintah
npm run server
di CLI lain.
Jika semuanya berjalan dengan baik, Anda akan melihat ini:
Mutasi Data
Memutasi data atau membuat data di Apollo Client hampir sama dengan mengkueri data, dengan sedikit perubahan.
Masih di client/src/pages/Pets.js
, mari salin dan tempel kode yang disorot:
.... const GET_PETS = gql` query getPets { pets { id name type img } } `;
const NEW_PETS = gql` mutation CreateAPet($newPet: NewPetInput!) { addPet(input: $newPet) { id name type img } } `;
const Pets = () => { const [modal, setModal] = useState(false) const { loading, error, data } = useQuery(GET_PETS);
const [createPet, newPet] = useMutation(NEW_PETS);
const onSubmit = input => { setModal(false)
createPet({ variables: { newPet: input } }); } if (loading || newPet.loading) return <Loader />; if (error || newPet.error) return <p>An error occured</p>;
if (modal) { return <NewPetModal onSubmit={onSubmit} onCancel={() => setModal(false)} /> } return ( <div className="page pets-page"> <section> <div className="row betwee-xs middle-xs"> <div className="col-xs-10"> <h1>Pets</h1> </div> <div className="col-xs-2"> <button onClick={() => setModal(true)}>new pet</button> </div> </div> </section> <section> <PetsList pets={data.pets}/> </section> </div> ) } export default Pets
Untuk membuat mutasi, kami akan mengambil langkah-langkah berikut.
1. mutation
Untuk membuat, memperbarui, atau menghapus, kita perlu melakukan operasi mutation
. Operasi mutation
memiliki nama CreateAPet
, dengan satu argumen. Argumen ini memiliki variabel $newPet
, dengan tipe NewPetInput
. !
berarti bahwa operasi diperlukan; dengan demikian, GraphQL tidak akan menjalankan operasi kecuali kita melewatkan variabel newPet
yang bertipe NewPetInput
.
2. addPet
Fungsi addPet
, yang berada di dalam operasi mutation
, mengambil argumen input
dan disetel ke variabel $newPet
kita. Kumpulan bidang yang ditentukan dalam fungsi addPet
kami harus sama dengan kumpulan bidang dalam kueri kami. Set bidang dalam operasi kami adalah:
-
id
-
name
-
type
-
img
3. useMutation
useMutation
React adalah API utama untuk mengeksekusi mutasi dalam aplikasi Apollo. Saat kita perlu mengubah data, kita memanggil useMutation
dalam komponen React dan meneruskannya sebagai string GraphQL (dalam kasus kita, NEW_PETS
).
Saat komponen kita merender useMutation
, ia mengembalikan sebuah tuple (yaitu, kumpulan data terurut yang merupakan catatan) dalam larik yang mencakup:
- fungsi
mutate
yang dapat kita panggil kapan saja untuk menjalankan mutasi; - objek dengan bidang yang mewakili status saat ini dari eksekusi mutasi.
Kait useMutation
dilewatkan string mutasi GraphQL (yang NEW_PETS
dalam kasus kami). Kami merusak tupel, yang merupakan fungsi ( createPet
) yang akan mengubah data dan bidang objek ( newPets
).
4. createPet
Dalam fungsi onSubmit
kami, tak lama setelah status setModal
, kami mendefinisikan createPet
kami. Fungsi ini mengambil variable
dengan properti objek dari nilai yang disetel ke { newPet: input }
. input
mewakili berbagai bidang input dalam formulir kami (seperti nama, jenis, dll.).
Setelah itu selesai, hasilnya akan terlihat seperti ini:
Jika Anda mengamati GIF dengan cermat, Anda akan melihat bahwa hewan peliharaan yang kita buat tidak langsung muncul, hanya saat halaman di-refresh. Namun, telah diperbarui di server.
Pertanyaan besarnya adalah, mengapa hewan peliharaan kita tidak segera diperbarui? Mari kita cari tahu di bagian selanjutnya.
Caching Di Klien Apollo
Alasan aplikasi kami tidak diperbarui secara otomatis adalah karena data kami yang baru dibuat tidak cocok dengan data cache di Klien Apollo. Jadi, ada konflik tentang apa sebenarnya yang perlu diperbarui dari cache.
Sederhananya, jika kita melakukan mutasi yang memperbarui atau menghapus banyak entri (sebuah node), maka kita bertanggung jawab untuk memperbarui semua kueri yang merujuk ke node tersebut, sehingga ia memodifikasi data yang di- cache agar sesuai dengan modifikasi yang dilakukan mutasi pada back- data akhir .
Menjaga Cache Tetap Sinkron
Ada beberapa cara untuk menjaga cache kita tetap sinkron setiap kali kita melakukan operasi mutasi.
Yang pertama adalah dengan mengambil ulang kueri yang cocok setelah mutasi, menggunakan properti objek refetchQueries
(cara paling sederhana).
Catatan: Jika kita menggunakan metode ini, itu akan mengambil properti objek dalam fungsi createPet
kita yang disebut refetchQueries
, dan itu akan berisi array objek dengan nilai kueri: refetchQueries: [{ query: GET_PETS }]
.
Karena fokus kami di bagian ini bukan hanya memperbarui hewan peliharaan yang kami buat di UI, tetapi untuk memanipulasi cache, kami tidak akan menggunakan metode ini.
Pendekatan kedua adalah dengan menggunakan fungsi update
. Di Klien Apollo, ada fungsi pembantu update
yang membantu memodifikasi data cache, sehingga disinkronkan dengan modifikasi yang dilakukan mutasi pada data back-end kami. Dengan menggunakan fungsi ini, kita dapat membaca dan menulis ke cache.
Memperbarui Cache
Salin kode yang disorot berikut, dan tempel di client/src/pages/Pets.js
:
...... const Pets = () => { const [modal, setModal] = useState(false) const { loading, error, data } = useQuery(GET_PETS);
const [createPet, newPet] = useMutation(NEW_PETS, { update(cache, { data: { addPet } }) { const data = cache.readQuery({ query: GET_PETS }); cache.writeQuery({ query: GET_PETS, data: { pets: [addPet, ...data.pets] }, }); }, } );
.....
Fungsi update
menerima dua argumen:
- Argumen pertama adalah cache dari Apollo Client.
- Yang kedua adalah respons mutasi yang tepat dari server. Kami merusak properti
data
dan mengaturnya ke mutasi kami (addPet
).
Selanjutnya, untuk memperbarui fungsi, kita perlu memeriksa kueri apa yang perlu diperbarui (dalam kasus kami, kueri GET_PETS
) dan membaca cache.
Kedua, kita perlu menulis ke query
yang dibaca, sehingga tahu kita akan memperbaruinya. Kami melakukannya dengan meneruskan objek yang berisi properti objek query
, dengan nilai yang disetel ke operasi query
kami ( GET_PETS
), dan properti data
yang nilainya adalah objek pet
dan yang memiliki larik mutasi addPet
dan salinan data hewan peliharaan.
Jika Anda mengikuti langkah-langkah ini dengan hati-hati, Anda akan melihat hewan peliharaan Anda diperbarui secara otomatis saat Anda membuatnya. Mari kita lihat perubahannya:
UI Optimis
Banyak orang adalah penggemar berat loader dan pemintal. Tidak ada salahnya menggunakan loader; ada kasus penggunaan yang sempurna di mana loader adalah pilihan terbaik. Saya telah menulis tentang pemuat versus pemintal dan kasus penggunaan terbaiknya.
Loader dan spinner memang memainkan peran penting dalam desain UI dan UX, tetapi kedatangan UI Optimis mencuri sorotan.
Apa itu UI Optimis?
UI Optimis adalah konvensi yang mensimulasikan hasil mutasi (data yang dibuat) dan memperbarui UI sebelum menerima respons dari server. Setelah respon diterima dari server, hasil optimis dibuang dan diganti dengan hasil yang sebenarnya.
Pada akhirnya, UI yang optimis tidak lebih dari cara untuk mengelola kinerja yang dirasakan dan menghindari status pemuatan.
Klien Apollo memiliki cara yang sangat menarik untuk mengintegrasikan UI Optimis. Ini memberi kita pengait sederhana yang memungkinkan kita untuk menulis ke cache lokal setelah mutasi. Mari kita lihat cara kerjanya!
Langkah 1
client/src/client.js
, dan tambahkan hanya kode yang disorot.
import { ApolloClient } from 'apollo-client' import { InMemoryCache } from 'apollo-cache-inmemory' import { HttpLink } from 'apollo-link-http'
import { setContext } from 'apollo-link-context' import { ApolloLink } from 'apollo-link' const http = new HttpLink({ uri: "https://localhost:4000/" }); const delay = setContext( request => new Promise((success, fail) => { setTimeout(() => { success() }, 800) }) ) const link = ApolloLink.from([ delay, http ])
const cache = new InMemoryCache() const client = new ApolloClient({ link, cache }) export default client
Langkah pertama melibatkan hal-hal berikut:
- Kami mengimpor
setContext
dariapollo-link-context
. FungsisetContext
mengambil fungsi panggilan balik dan mengembalikan janji yangsetTimeout
diatur ke800ms
, untuk membuat penundaan saat operasi mutasi dilakukan. - Metode
ApolloLink.from
memastikan bahwa aktivitas jaringan yang mewakili tautan (API kami) dariHTTP
tertunda.
Langkah 2
Langkah selanjutnya adalah menggunakan kait UI Optimis. Geser kembali ke client/src/pages/Pets.js
, dan tambahkan hanya kode yang disorot di bawah ini.
..... const Pets = () => { const [modal, setModal] = useState(false) const { loading, error, data } = useQuery(GET_PETS); const [createPet, newPet] = useMutation(NEW_PETS, { update(cache, { data: { addPet } }) { const data = cache.readQuery({ query: GET_PETS }); cache.writeQuery({ query: GET_PETS, data: { pets: [addPet, ...data.pets] }, }); }, } ); const onSubmit = input => { setModal(false) createPet({ variables: { newPet: input },
optimisticResponse: { __typename: 'Mutation', addPet: { __typename: 'Pet', id: Math.floor(Math.random() * 10000 + ''), name: input.name, type: input.type, img: 'https://via.placeholder.com/200' } }
}); } .....
Objek optimisticResponse
digunakan jika kita ingin UI segera diperbarui saat kita membuat hewan peliharaan, alih-alih menunggu respons server.
Cuplikan kode di atas termasuk yang berikut:
-
__typename
disuntikkan oleh Apollo ke dalam kueri untuk mengambiltype
entitas yang ditanyakan. Jenis tersebut digunakan oleh Apollo Client untuk membangun propertiid
(yang merupakan simbol) untuk tujuan caching diapollo-cache
. Jadi,__typename
adalah properti yang valid dari respons kueri. - Mutasi ditetapkan sebagai
__typename
darioptimisticResponse
. - Seperti yang didefinisikan sebelumnya, nama mutasi kita adalah
addPet
, dan__typename
adalahPet
. - Berikut adalah bidang-bidang mutasi kami yang kami ingin respons optimis untuk diperbarui:
-
id
Karena kami tidak tahu ID dari servernya nanti, kami membuatnya menggunakanMath.floor
. -
name
Nilai ini diatur keinput.name
. -
type
Nilai tipenya adalahinput.type
. -
img
Sekarang, karena server kami menghasilkan gambar untuk kami, kami menggunakan placeholder untuk meniru gambar kami dari server.
-
Ini memang perjalanan yang panjang. Jika Anda sampai di akhir, jangan ragu untuk beristirahat dari kursi Anda dengan secangkir kopi.
Mari kita lihat hasil kita. Repositori pendukung untuk proyek ini ada di GitHub. Kloning dan bereksperimenlah dengannya.
Kesimpulan
Fitur luar biasa dari Apollo Client, seperti UI Optimis dan pagination, membuat pembuatan aplikasi sisi klien menjadi kenyataan.
Sementara Apollo Client bekerja sangat baik dengan kerangka kerja lain, seperti Vue.js dan Angular, pengembang React memiliki Apollo Client Hooks, sehingga mereka tidak bisa tidak menikmati membangun aplikasi yang hebat.
Dalam artikel ini, kita hanya menggores permukaannya saja. Menguasai Apollo Client menuntut latihan terus-menerus. Jadi, lanjutkan dan klon repositori, tambahkan pagination, dan bermain-main dengan fitur lain yang ditawarkannya.
Silakan bagikan tanggapan dan pengalaman Anda di bagian komentar di bawah. Kami juga dapat mendiskusikan kemajuan Anda di Twitter. Bersulang!
Referensi
- “GraphQL Sisi Klien Dalam Bereaksi”, Scott Moss, Frontend Master
- "Dokumentasi", Klien Apollo
- “UI Optimis Dengan Bereaksi”, Patryk Andrzejewski
- “Kebohongan Sejati Dari Antarmuka Pengguna yang Optimis”, Majalah Smashing