React Uygulamalarında Apollo-Client ile İstemci Tarafı Grafiği Anlamak

Yayınlanan: 2022-03-10
Hızlı özet ↬ Hiç bir istemci tarafı uygulamasında bir GraphQL sunucusuyla etkileşim kurmayı denediniz ve bir yere varmadan önce pes etmek istediniz mi? Hiç fikriniz olmadığı için GraphQL API ile çalışmayı gerektiren bir kod tabanına katılma davetini reddettiniz mi? Hiç GraphQL API'lerini kullanmayı öğrenmemiş tek ön uç mühendisi gibi hissettiniz mi? Bu sorulardan herhangi birine evet yanıtı verdiyseniz, bu eğitim tam size göre. GraphQL ve Apollo Client'ın birkaç temeline ve her ikisiyle nasıl çalışılacağına daha yakından bakacağız. Sonunda, Apollo Client kullanan bir evcil hayvan dükkanı uygulaması oluşturmuş olacağız. Ardından, bir sonraki projenizi oluşturmaya devam edebilirsiniz.

State of JavaScript 2019'a göre, geliştiricilerin %38,7'si GraphQL'i kullanmak isterken, geliştiricilerin %50,8'i GraphQL öğrenmek istiyor.

Bir sorgu dili olan GraphQL, bir istemci uygulaması oluşturma iş akışını basitleştirir. Gerekli verileri getirmek için tek bir HTTP uç noktası sunduğundan, istemci tarafı uygulamalarda API uç noktalarını yönetmenin karmaşıklığını ortadan kaldırır. Bu nedenle, REST durumunda olduğu gibi verilerin aşırı yüklenmesini ve yetersiz yüklenmesini ortadan kaldırır.

Ancak GraphQL sadece bir sorgulama dilidir. Kolayca kullanabilmemiz için bizim yerimize ağır işleri yapan bir platforma ihtiyacımız var. Böyle bir platform Apollo'dur.

Apollo platformu, bulut (sunucu) arasında uygulamanızın kullanıcı arayüzüne veri aktaran bir GraphQL uygulamasıdır. Apollo Client'ı kullandığınızda, veri alma, izleme, yükleme ve kullanıcı arabirimini güncelleme mantığının tümü useQuery kancası tarafından kapsanır (React durumunda olduğu gibi). Bu nedenle, veri alma bildirimseldir. Ayrıca sıfır yapılandırmalı önbelleğe alma özelliğine sahiptir. Yalnızca uygulamanızda Apollo Client'ı kurarak, ek yapılandırma gerektirmeden kutudan çıktığı gibi akıllı bir önbellek elde edersiniz.

Apollo Client ayrıca Angular, Vue.js ve React gibi diğer çerçevelerle birlikte çalışabilir.

Not : Bu eğitim, geçmişte istemci tarafında RESTful veya diğer API biçimleriyle çalışmış ve GraphQL'nin denemeye değer olup olmadığını görmek isteyenlere fayda sağlayacaktır. Bu, daha önce bir API ile çalışmış olmanız gerektiği anlamına gelir; ancak o zaman GraphQL'in sizin için ne kadar faydalı olabileceğini anlayabileceksiniz. GraphQL ve Apollo Client'ın birkaç temel özelliğini ele alacak olsak da, iyi bir JavaScript ve React Hooks bilgisi işe yarayacaktır.

GraphQL Temelleri

Bu makale GraphQL'e tam bir giriş değildir, ancak devam etmeden önce birkaç kuralı tanımlayacağız.

GraphQL Nedir?

GraphQL, müşterilerinizin tam olarak istedikleri verileri bir API'ye sormak için kullanabilecekleri bildirime dayalı bir sorgu dilini tanımlayan bir belirtimdir. Bu, API'niz için en üst düzeyde esneklikle güçlü bir tür şeması oluşturarak elde edilir. Ayrıca API'nin verileri çözmesini ve istemci sorgularının bir şemaya göre doğrulanmasını sağlar. Bu tanım, GraphQL'nin, statik olarak yazılan (Typescript çevresinde oluşturulmuş) bir API ile onu bildirimsel bir sorgu dili yapan ve müşterinin istediği tam verileri API'den istemek için bu tür sistemlerden yararlanmasını sağlayan bazı spesifikasyonlar içerdiği anlamına gelir. .

Yani, içinde bazı alanlar olan bazı tipler oluştursaydık, o zaman client tarafından “Bu verileri tam olarak bu alanlar ile bize verin” diyebiliriz. Ardından API, tıpkı güçlü bir şekilde yazılmış bir dilde bir tür sistemi kullanıyormuşuz gibi, tam olarak bu şekilde yanıt verecektir. TypeScript makalemde daha fazla bilgi edinebilirsiniz.

Devam ederken bize yardımcı olacak bazı GraphQl kurallarına bakalım.

Temeller

  • Operasyonlar
    GraphQL'de gerçekleştirilen her eyleme operasyon denir. Birkaç işlem vardır, yani:
    • Sorgu
      Bu işlem, sunucudan veri almakla ilgilidir. Buna salt okunur getirme de diyebilirsiniz.
    • mutasyon
      Bu işlem, bir sunucudan veri oluşturmayı, güncellemeyi ve silmeyi içerir. Yaygın olarak CUD (oluşturma, güncelleme ve silme) işlemi olarak adlandırılır.
    • abonelikler
      GraphQL'deki bu işlem, belirli olaylar meydana geldiğinde bir sunucudan istemcilerine veri göndermeyi içerir. Genellikle WebSockets ile uygulanırlar.

Bu yazımızda sadece sorgulama ve mutasyon işlemleri ile ilgileneceğiz.

  • İşlem adları
    İstemci tarafı sorgu ve mutasyon işlemleriniz için benzersiz adlar vardır.
  • Değişkenler ve argümanlar
    İşlemler, çoğu programlama dilindeki bir işleve çok benzer şekilde argümanları tanımlayabilir. Bu değişkenler daha sonra operasyon içindeki sorgulama veya mutasyon çağrılarına argüman olarak iletilebilir. İstemcinizden bir işlemin yürütülmesi sırasında değişkenlerin çalışma zamanında verilmesi beklenir.
  • takma
    Bu, kullanıcı arabirimi için basit ve okunabilir alan adlarıyla ayrıntılı veya belirsiz alan adlarının yeniden adlandırılmasını içeren istemci tarafı GraphQL'deki bir kuraldır. Çakışan alan adlarına sahip olmak istemediğiniz kullanım durumlarında takma ad gereklidir.
GraphQL temel kuralları
GraphQL temel kuralları. (Büyük önizleme)
Atlamadan sonra daha fazlası! Aşağıdan okumaya devam edin ↓

İstemci Tarafı GraphQL Nedir?

Bir ön uç mühendisi, Vue.js veya (bizim durumumuzda) React gibi herhangi bir çerçeveyi kullanarak UI bileşenleri oluşturduğunda, bu bileşenler sunucudan alınacak verilere uyacak şekilde istemcide belirli bir kalıptan modellenir ve tasarlanır.

RESTful API'lerle ilgili en yaygın sorunlardan biri aşırı ve eksik getirmedir. Bunun nedeni, bir istemcinin verileri indirmesinin tek yolunun, sabit veri yapılarını döndüren uç noktalara ulaşmak olmasıdır. Bu bağlamda aşırı yükleme, bir istemcinin uygulamanın gerektirdiğinden daha fazla bilgi indirmesi anlamına gelir.

GraphQL'de ise, gerekli verileri içeren GraphQL sunucusuna tek bir sorgu göndermeniz yeterlidir. Sunucu daha sonra tam olarak istediğiniz verinin bir JSON nesnesiyle yanıt verir - bu nedenle aşırı yükleme olmaz. Sebastian Eschweiler, RESTful API'ler ve GraphQL arasındaki farkları açıklıyor.

İstemci tarafı GraphQL, aşağıdaki işlevleri gerçekleştirmek için bir GraphQL sunucusundan alınan verilerle arayüz oluşturan bir istemci tarafı altyapısıdır:

  • HTTP istekleri oluşturmanıza gerek kalmadan sorgular göndererek ve verileri mutasyona uğratarak verileri yönetir. Tesisat verileri için daha az, gerçek uygulamayı oluşturmak için daha fazla zaman harcayabilirsiniz.
  • Bir önbelleğin karmaşıklığını sizin için yönetir. Böylece, sunucudan alınan verileri herhangi bir üçüncü taraf müdahalesi olmadan depolayabilir ve alabilir ve yinelenen kaynakları yeniden almaktan kolayca kaçınabilirsiniz. Böylece, karmaşık bir uygulama için harika olan iki kaynağın aynı olduğunu tanımlar.
  • Kullanıcı arabiriminizi, bir mutasyonun sonuçlarını (yani oluşturulan veriler) simüle eden ve sunucudan bir yanıt almadan önce bile kullanıcı arabirimini güncelleyen bir kural olan İyimser Kullanıcı Arabirimi ile tutarlı tutar. Sunucudan yanıt alındıktan sonra, iyimser sonuç atılır ve gerçek sonuçla değiştirilir.

İstemci tarafı GraphQL hakkında daha fazla bilgi için, GraphQL'in yaratıcısı ve GraphQL Radio'daki diğer harika insanlarla bir saat ayırın.

Apollo İstemcisi Nedir?

Apollo Client, JavaScript ve yerel platformlar için birlikte çalışabilir, ultra esnek, topluluk odaklı bir GraphQL istemcisidir. Etkileyici özellikleri arasında sağlam bir durum yönetimi aracı (Apollo Link), sıfır yapılandırmalı bir önbelleğe alma sistemi, veri almaya yönelik bildirimsel bir yaklaşım, uygulaması kolay sayfalandırma ve istemci tarafı uygulamanız için İyimser Kullanıcı Arabirimi bulunur.

Apollo İstemcisi, yalnızca sunucudan alınan verilerdeki durumu değil, aynı zamanda istemcinizde yerel olarak oluşturduğu durumu da saklar; bu nedenle, hem API verileri hem de yerel veriler için durumu yönetir.

Apollo Client'ı Redux gibi diğer durum yönetimi araçlarıyla çakışmadan kullanabileceğinizi de belirtmek önemlidir. Ayrıca, durum yönetiminizi örneğin Redux'tan Apollo Client'a (bu makalenin kapsamı dışındadır) taşımak mümkündür. Sonuç olarak, Apollo Client'ın temel amacı, mühendislerin bir API'deki verileri sorunsuz bir şekilde sorgulamasını sağlamaktır.

Apollo İstemcisinin Özellikleri

Apollo Client, modern sağlam uygulamalar oluşturmayı çok kolay hale getiren son derece yararlı özellikleri nedeniyle pek çok mühendis ve şirketi kazandı. Aşağıdaki özellikler fırınlanmıştır:

  • Önbelleğe almak
    Apollo Client, anında önbelleğe almayı destekler.
  • İyimser kullanıcı arayüzü
    Apollo Client, İyimser Kullanıcı Arayüzü için harika bir desteğe sahiptir. İşlem devam ederken bir işlemin (mutasyon) son durumunun geçici olarak görüntülenmesini içerir. İşlem tamamlandığında, gerçek veriler iyimser verilerin yerini alır.
  • sayfalandırma
    Apollo Client, uygulamanızda sayfalandırmayı uygulamayı oldukça kolaylaştıran yerleşik bir işlevselliğe sahiptir. useQuery kancasıyla birlikte gelen fetchMore işlevini kullanarak, yamalar halinde veya bir kerede bir veri listesi getirmenin teknik sorunlarının çoğunu halleder.

Bu yazıda, bu özelliklerin bir seçimine bakacağız.

Teori yeter. Ellerimizi kirletirken emniyet kemerinizi sıkın ve kreplerinizin yanına bir kahve alın.

Web Uygulamamızı Oluşturma

Bu proje Scott Moss'tan ilham almıştır.

Özellikleri arasında aşağıdakileri içeren basit bir evcil hayvan dükkanı web uygulaması oluşturacağız:

  • evcil hayvanlarımızı sunucu tarafından almak;
  • bir evcil hayvan oluşturma (ad, evcil hayvan türü ve görüntü oluşturmayı içerir);
  • İyimser kullanıcı arayüzünü kullanarak;
  • verilerimizi bölümlere ayırmak için sayfalama kullanma.

Başlamak için, starter ​​dalının klonladığınız şey olduğundan emin olarak depoyu klonlayın.

Başlarken

  • Chrome için Apollo Client Developer Tools uzantısını yükleyin.
  • Komut satırı arabirimini (CLI) kullanarak klonlanmış havuzun dizinine gidin ve tüm bağımlılıkları almak için şu komutu çalıştırın: npm install .
  • Uygulamayı başlatmak için npm run app komutunu çalıştırın.
  • Hala kök klasördeyken, npm run server komutunu çalıştırın. Bu, ilerlerken kullanacağımız arka uç sunucumuzu başlatacak.

Uygulama, yapılandırılmış bir bağlantı noktasında açılmalıdır. Benimki https://localhost:1234/ ; seninki muhtemelen başka bir şeydir.

Her şey yolunda gittiyse, uygulamanız şöyle görünmelidir:

Klonlanmış başlangıç ​​dalı kullanıcı arayüzü
Klonlanmış başlangıç ​​dalı kullanıcı arabirimi. (Büyük önizleme)

Gösterecek evcil hayvanımız olmadığını fark edeceksiniz. Çünkü henüz böyle bir işlevsellik yaratmadık.

Apollo Client Developer Tools'u doğru bir şekilde kurduysanız, geliştirici araçlarını açın ve tepsi simgesine tıklayın. “Apollo” ve bunun gibi bir şey göreceksiniz:

Apollo İstemci Geliştirici Araçları
Apollo İstemci Geliştirici Araçları. (Büyük önizleme)

Redux ve React geliştirici araçları gibi, sorgularımızı ve mutasyonlarımızı yazmak ve test etmek için Apollo İstemci Geliştirici Araçlarını kullanacağız. Uzantı, GraphQL Playground ile birlikte gelir.

Evcil Hayvan Getirmek

Evcil hayvanları getiren işlevselliği ekleyelim. client/src/client.js . Apollo İstemcisi yazacağız, onu bir API'ye bağlayacağız, onu varsayılan istemci olarak dışa aktaracağız ve yeni bir sorgu yazacağız.

Aşağıdaki kodu kopyalayın ve client.js yapıştırın:

 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

İşte yukarıda neler olduğuna dair bir açıklama:

  • ApolloClient
    Bu, uygulamamızı tamamlayan ve böylece HTTP ile arayüz oluşturan, verileri önbelleğe alan ve kullanıcı arayüzünü güncelleyen işlev olacaktır.
  • InMemoryCache
    Bu, uygulamamızdaki önbelleği değiştirmeye yardımcı olan Apollo İstemcisindeki normalleştirilmiş veri deposudur.
  • HttpLink
    Bu, GraphQL isteklerinin kontrol akışını değiştirmek ve GraphQL sonuçlarını getirmek için standart bir ağ arabirimidir. Bağlantı her başlatıldığında GraphQL sunucusundan sonuçları getiren ara katman yazılımı görevi görür. Ayrıca, Axios ve window.fetch gibi diğer seçenekler için iyi bir alternatiftir.
  • HttpLink örneğine atanan bir bağlantı değişkeni bildiririz. https://localhost:4000/ olan sunucumuza bir uri özelliği ve bir değer alır.
  • Sonraki, InMemoryCache yeni örneğini tutan bir önbellek değişkenidir.
  • İstemci değişkeni ayrıca ApolloClient örneğini alır ve link ve cache sarar.
  • Son olarak, client uygulama genelinde kullanabilmemiz için dışa aktarıyoruz.

Bunu çalışırken görmeden önce, tüm uygulamamızın Apollo'ya maruz kaldığından ve uygulamamızın sunucudan alınan verileri alabildiğinden ve bu verileri değiştirebildiğinden emin olmalıyız.

Bunu başarmak için client/src/index.js gidelim:

 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() }

Vurgulanan kodda farkedeceğiniz gibi, App bileşenini ApolloProvider ve istemciyi client bir destek olarak ilettik. ApolloProvider , React'in Context.Provider öğesine benzer. React uygulamanızı sarar ve istemciyi, bileşen ağacınızın herhangi bir yerinden ona erişmenizi sağlayan bir bağlama yerleştirir.

Petlerimizi sunucudan almak için tam olarak istediğimiz alanları talep eden sorgular yazmamız gerekiyor. client/src/pages/Pets.js ve aşağıdaki kodu kopyalayıp içine yapıştırın:

 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> ) }

Birkaç bit kod ile petleri sunucudan getirebiliyoruz.

gql nedir?

GraphQL'deki işlemlerin genellikle graphql-tag ve ters tiklerle yazılmış JSON nesneleri olduğuna dikkat etmek önemlidir.

gql etiketleri, GraphQL sorgu dizelerini GraphQL AST'ye (soyut sözdizimi ağacı) ayrıştıran JavaScript şablonu değişmez etiketleridir.

  • Sorgu işlemleri
    Petlerimizi sunucudan almak için bir sorgulama işlemi yapmamız gerekiyor.
    • query işlemi yaptığımız için isim vermeden önce işlemin type belirtmemiz gerekiyordu.
    • Sorgumuzun adı GET_PETS . Alan adları için camelCase kullanmak GraphQL'nin bir adlandırma kuralıdır.
    • Tarlalarımızın adı pets . Bu nedenle sunucudan tam olarak ihtiyacımız olan alanları belirtiyoruz (id, name, type, img) .
    • useQuery , bir Apollo uygulamasında sorguları yürütmenin temeli olan bir React kancasıdır. React bileşenimizde bir sorgu işlemi gerçekleştirmek için, başlangıçta @apollo/react-hooks hooks'tan içe aktarılan useQuery kancasını çağırırız. Ardından, bizim durumumuzda GET_PETS olan bir GraphQL sorgu dizesini iletiyoruz.
  • Bileşenimiz useQuery , Apollo İstemcisinden yükleme, hata ve veri özelliklerini içeren bir nesne yanıtı döndürür. Böylece, onları kullanıcı arayüzünü oluşturmak için kullanabilmemiz için tahrip edilmişlerdir.
  • useQuery harika. async-await dahil etmek zorunda değiliz. Arka planda zaten halledildi. Çok güzel, değil mi?
    • loading
      Bu özellik, uygulamanın yükleme durumunu ele almamıza yardımcı olur. Bizim durumumuzda, uygulamamız yüklenirken bir Loader bileşeni döndürürüz. Varsayılan olarak, yükleme false .
    • error
      Her ihtimale karşı, meydana gelebilecek herhangi bir hatayı işlemek için bu özelliği kullanıyoruz.
    • data
      Bu, sunucudaki gerçek verilerimizi içerir.
    • Son olarak, PetsList bileşenimizde, bir nesne değeri olarak data.pets ile pets props'larını geçiyoruz.

Bu noktada sunucumuzu başarıyla sorguladık.

Uygulamamızı başlatmak için aşağıdaki komutu çalıştıralım:

  • İstemci uygulamasını başlatın. npm run app komutunu çalıştırın.
  • Sunucuyu başlatın. Başka bir npm run server komutunu çalıştırın.
VScode CLI, hem istemciyi hem de sunucuyu başlatmak için bölümlenir.
VScode CLI, hem istemciyi hem de sunucuyu başlatmak için bölümlenir. (Büyük önizleme)

Her şey yolunda gittiyse şunu görmelisiniz:

Sunucudan sorgulanan evcil hayvanlar.
Sunucudan sorgulanan evcil hayvanlar.

Mutasyona Uğrayan Veriler

Apollo İstemcisinde verileri mutasyona uğratmak veya veri oluşturmak, çok küçük değişikliklerle, verileri sorgulamakla hemen hemen aynıdır.

Hala client/src/pages/Pets.js , vurgulanan kodu kopyalayıp yapıştıralım:

 .... 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

Bir mutasyon oluşturmak için aşağıdaki adımları atardık.

1. mutation

Oluşturmak, güncellemek veya silmek için mutation işlemini yapmamız gerekiyor. mutation işlemi, tek argümanlı bir CreateAPet adına sahiptir. Bu bağımsız değişken, NewPetInput türünde bir $newPet NewPetInput . ! işlemin gerekli olduğu anlamına gelir; bu nedenle, türü NewPetInput olan bir newPet değişkeni iletmedikçe GraphQL işlemi NewPetInput .

2. addPet

mutation işleminin içindeki addPet işlevi, input argümanını alır ve $newPet değişkenimize ayarlanır. addPet belirtilen alan kümeleri, sorgumuzdaki alan kümelerine eşit olmalıdır. Operasyonumuzdaki alan kümeleri şunlardır:

  • id
  • name
  • type
  • img

3. useMutation

useMutation React kancası, bir Apollo uygulamasında mutasyonları yürütmek için birincil API'dir. Verileri mutasyona uğratmamız gerektiğinde, bir React bileşeninde useMutation çağırır ve ona bir GraphQL dizesi iletiriz (bizim durumumuzda NEW_PETS ).

Bileşenimiz useMutation oluşturduğunda, aşağıdakileri içeren bir dizide bir tanımlama grubu (yani, bir kaydı oluşturan sıralı bir veri kümesi) döndürür:

  • mutasyonu yürütmek için herhangi bir zamanda arayabileceğimiz bir mutate işlevi;
  • mutasyonun yürütülmesinin mevcut durumunu temsil eden alanları olan bir nesne.

useMutation kancası, bir GraphQL mutasyon dizgisinden geçirilir (bizim durumumuzda NEW_PETS olan). Verileri ve nesne alanını ( newPets ) değiştirecek olan işlev ( createPet ) olan demeti bozduk.

4. createPet

onSubmit fonksiyonumuzda createPet setModal Bu işlev, { newPet: input } olarak ayarlanmış bir değerin nesne özelliğine sahip bir variable alır. input , formumuzdaki çeşitli giriş alanlarını temsil eder (ad, tür vb. gibi).

Bunu yaptıktan sonra, sonuç şöyle görünmelidir:

Anında güncelleme olmadan mutasyon
Anında güncelleme olmadan mutasyon.

GIF'i yakından incelerseniz, yarattığımız petin anında değil, sadece sayfa yenilendiğinde ortaya çıktığını fark edeceksiniz. Ancak, sunucuda güncellendi.

Asıl soru, evcil hayvanımız neden anında güncellenmiyor? Bir sonraki bölümde öğrenelim.

Apollo İstemcisinde Önbelleğe Alma

Uygulamamızın otomatik olarak güncellenmemesinin nedeni, yeni oluşturulan verilerimizin Apollo İstemcisindeki önbellek verileriyle eşleşmemesidir. Bu nedenle, önbellekten tam olarak neyin güncellenmesi gerektiğine dair bir çelişki var.

Basitçe söylemek gerekirse, birden fazla girişi (bir düğüm) güncelleyen veya silen bir mutasyon gerçekleştirirsek, o düğüme atıfta bulunan tüm sorguları güncellemekten sorumluyuz, böylece önbelleğe alınmış verilerimizi bir mutasyonun arkamızda yaptığı değişikliklerle eşleşecek şekilde değiştirir. son veri.

Önbelleği Senkronize Tutmak

Her mutasyon işlemi yaptığımızda önbelleğimizi senkronize tutmanın birkaç yolu vardır.

Birincisi, bir mutasyondan sonra, refetchQueries nesne özelliğini (en basit yol) kullanarak eşleşen sorguları yeniden getirmektir.

Not: Bu yöntemi kullanacak olsaydık, createPet refetchQueries bir nesne özelliği alırdı ve sorgu değerine sahip bir dizi nesne refetchQueries: [{ query: GET_PETS }] .

Bu bölümdeki odak noktamız yalnızca kullanıcı arayüzünde oluşturulan evcil hayvanlarımızı güncellemek değil, aynı zamanda önbelleği değiştirmek olduğundan, bu yöntemi kullanmayacağız.

İkinci yaklaşım, update işlevini kullanmaktır. Apollo Client'ta, bir mutasyonun arka uç verimizde yaptığı değişikliklerle senkronize olması için önbellek verilerini değiştirmeye yardımcı olan bir update yardımcı işlevi vardır. Bu fonksiyonu kullanarak önbelleğe okuyup yazabiliriz.

Önbelleği Güncelleme

Aşağıdaki vurgulanan kodu kopyalayın ve 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] }, }); }, } );
 .....

update işlevi iki argüman alır:

  • İlk argüman Apollo İstemcisinden gelen önbellektir.
  • İkincisi, sunucudan gelen kesin mutasyon yanıtıdır. data özelliğini bozarız ve onu mutasyonumuza ( addPet ) ayarlarız.

Ardından, işlevi güncellemek için hangi sorgunun güncellenmesi gerektiğini (bizim durumumuzda GET_PETS sorgusu) kontrol etmemiz ve önbelleği okumamız gerekir.

İkinci olarak, güncelleyeceğimizi bilmesi için okunan query yazmamız gerekir. Bunu, değeri query işlemimize ( GET_PETS ) ayarlanmış bir query nesnesi özelliği ve değeri bir pet nesnesi olan ve addPet mutasyonunun bir dizisine ve bir kopyasına sahip bir data özelliği içeren bir nesneyi ileterek yaparız. evcil hayvan verileri.

Bu adımları dikkatli bir şekilde takip ettiyseniz, evcil hayvanlarınızı oluştururken otomatik olarak güncellendiğini görmelisiniz. Değişikliklere bir göz atalım:

Evcil hayvanlar anında güncellenir
Evcil hayvanlar anında güncellenir.

İyimser kullanıcı arayüzü

Pek çok insan, yükleyicilerin ve eğiricilerin büyük hayranlarıdır. Bir yükleyici kullanmanın yanlış bir tarafı yok; bir yükleyicinin en iyi seçenek olduğu mükemmel kullanım durumları vardır. Yükleyiciler ve iplikçiler ve bunların en iyi kullanım durumları hakkında yazdım.

Yükleyiciler ve eğiriciler gerçekten de UI ve UX tasarımında önemli bir rol oynuyor, ancak Optimistic UI'nin gelişi dikkatleri üzerine çekti.

İyimser Kullanıcı Arayüzü Nedir?

İyimser UI, bir mutasyonun (oluşturulan veri) sonuçlarını simüle eden ve sunucudan bir yanıt almadan önce UI'yi güncelleyen bir kuraldır. Sunucudan yanıt alındıktan sonra, iyimser sonuç atılır ve gerçek sonuçla değiştirilir.

Sonunda, iyimser bir kullanıcı arayüzü, algılanan performansı yönetmenin ve yükleme durumlarından kaçınmanın bir yolundan başka bir şey değildir.

Apollo Client, İyimser Kullanıcı Arayüzünü entegre etmenin çok ilginç bir yoluna sahiptir. Mutasyondan sonra yerel önbelleğe yazmamıza izin veren basit bir kanca verir. Nasıl çalıştığını görelim!

Aşama 1

client/src/client.js ve yalnızca vurgulanan kodu ekleyin.

 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

İlk adım aşağıdakileri içerir:

  • setContext apollo-link-context context'ten içe aktarıyoruz. setContext işlevi bir geri arama işlevi alır ve bir mutasyon işlemi gerçekleştirildiğinde bir gecikme oluşturmak için setTimeout 800ms olarak ayarlanmış bir söz verir.
  • ApolloLink.from yöntemi, HTTP gelen bağlantıyı (bizim API'miz) temsil eden ağ etkinliğinin ertelenmesini sağlar.

Adım 2

Bir sonraki adım, İyimser UI kancasını kullanmaktır. client/src/pages/Pets.js geri kaydırın ve yalnızca aşağıda vurgulanan kodu ekleyin.

 ..... 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' } }
 }); } .....

Bir evcil hayvan oluşturduğumuzda, sunucu yanıtını beklemek yerine kullanıcı arabiriminin hemen güncellenmesini istiyorsak optimisticResponse nesnesi kullanılır.

Yukarıdaki kod parçacıkları aşağıdakileri içerir:

  • __typename , sorgulanan varlıkların type getirmek için Apollo tarafından sorguya enjekte edilir. Bu türler, Apollo Client tarafından apollo-cache içinde önbelleğe alma amacıyla id özelliğini (bir sembol olan) oluşturmak için kullanılır. Bu nedenle, __typename , sorgu yanıtının geçerli bir özelliğidir.
  • Mutasyon, optimisticResponse __typename olarak ayarlanır.
  • Daha önce tanımlandığı gibi, mutasyonumuzun adı addPet ve __typename Pet
  • Sırada, iyimser yanıtın güncellenmesini istediğimiz mutasyonumuzun alanları var:
    • id
      Sunucudan gelen kimliğin ne olacağını bilmediğimiz için Math.floor kullanarak bir tane oluşturduk.
    • name
      Bu değer input.name olarak ayarlanır.
    • type
      Türün değeri input.type .
    • img
      Şimdi, sunucumuz bizim için resimler oluşturduğundan, sunucudaki resmimizi taklit etmek için bir yer tutucu kullandık.

Bu gerçekten uzun bir yolculuktu. Sona ulaştıysanız, kahvenizle sandalyenizden biraz mola vermekten çekinmeyin.

Sonucumuza bir göz atalım. Bu proje için destekleyici depo GitHub'da. Klonlayın ve onunla deney yapın.

Evcil hayvan dükkanı uygulamasının Nihai Sonucu
Uygulamamızın nihai sonucu.

Çözüm

Apollo Client'ın İyimser Kullanıcı Arayüzü ve sayfalandırma gibi şaşırtıcı özellikleri, istemci tarafı uygulamaları oluşturmayı gerçeğe dönüştürür.

Apollo Client, Vue.js ve Angular gibi diğer çerçevelerle çok iyi çalışsa da, React geliştiricilerinin Apollo Client Hooks'u vardır ve bu nedenle harika bir uygulama oluşturmanın keyfini çıkaramazlar.

Bu yazıda sadece yüzeyi çizdik. Apollo İstemcisinde Ustalaşmak, sürekli pratik gerektirir. Öyleyse devam edin ve depoyu klonlayın, sayfalandırma ekleyin ve sunduğu diğer özelliklerle oynayın.

Lütfen geri bildiriminizi ve deneyiminizi aşağıdaki yorumlar bölümünde paylaşın. İlerlemenizi Twitter'da da tartışabiliriz. Şerefe!

Referanslar

  • “İstemci Tarafı GraphQL In React”, Scott Moss, Ön Uç Ustası
  • "Belgeleme", Apollo İstemcisi
  • “React ile İyimser Kullanıcı Arayüzü”, Patryk Andrzejewski
  • “İyimser Kullanıcı Arayüzlerinin Gerçek Yalanları”, Smashing Magazine