Witajcie w już trzecim poście dotyczącym GraphQL. Jeśli ominęliście je to gorąco zachęcam do odwiedzenia: Jak zacząć zabawę z GraphQL oraz Typy i schematy w GrapQL. Jednak odbieranie danych to za mało. Musimy mieć możliwość wysyłania własnych danych. Dziś opiszę jak można w tym języku zapytań to zrobić przy pomocy mutacji(mutation).
Przekazywanie argumentów
Jednak zanim przejdę do właściwej części, w której pokażę jak wykonywać zapytania Insert i Delete zatrzymam się jeszcze na chwilę w zwykłych zapytaniach. Bardzo często nie potrzebujemy listy ze wszystkimi danymi. Zazwyczaj potrzebujemy tylko jeden konkretny element by go wyświetlić lub zedytować. W GraphQL do tego celu możemy wykorzystać przekazywanie argumentów. W schemacie możemy sobie zdefiniować nowe pole o takiej strukturze:
getPost(id:ID!):Post
Dzięki temu takie pole może przyjmować dodatkowe argumenty. To została nam jeszcze funkcja zwracająca wynik:
getPost:({id})=>posts[id],
Warto zauważyć, że argumentem jest obiekt. Tak samo muszą być przekazane dane podczas tworzenia zapytania. Nie możemy po prostu przekazać wartości, ponieważ dostaniemy następujący błąd: Przy wysyłaniu zapytania musimy wysłać obiekt z nazwami pól odpowiadającymi tym, które zdefiniowaliśmy w schemacie.
Mutacje
Mutacje są specjalnym rodzajem zapytania, które ma zmodyfikować dane na serwerze czyli będzie to odpowiednik INSERT, EDIT i DELETE z REST’a. Definiuje się je i używa podobnie do zwykłych zapytań a szczególnie pokazanych w poprzednim paragrafie zapytań z argumentem. Zapytania z tej grupy umieszczamy w specjalnym typie wewnątrz schematu:
type Mutation{
}
Mając coś takiego można tworzyć pola, które są nam potrzebne. Tworzymy je identycznie jak podczas przekazywania argumentów:
addPost(title:String,author:String):Post,
I od razu funkcję która to obsłuży :
addPost:({title,author})=>{
posts[nextIndex]={title,author};
nextIndex++;
return {title,author};
},
Nad tworzeniem zapytań warto się chwilę zatrzymać ponieważ wygląda trochę inaczej. Pierwsza różnica to słowo kluczowe mutation
na początku zapytania. Drugie to musimy podać jakie pola chcemy otrzymać z powrotem.
Bez tego dostaniemy następujący błąd:
Da się to ominąć ustawiając w schemacie zwracany typ na Boolean
addPost(title:String,author:String):Boolean
Wtedy możemy wykonać następujące zapytanie i nie dostaniemy błędu:
Na sam koniec jeszcze wspomnę o możliwości zebrania wszystkich wymaganych pól, które należy przekazać w postaci obiektu. Nie możemy tutaj użyć słówka kluczowego type
ale mamy za to słówko kluczowe input
. Może to wyglądać w następujący sposób:
inputPostInput{
title:String,
author:String
}
type Mutation{
addPost(post:PostInput):Post,
}
addPost:({post})=>{
posts[nextIndex]=post;
nextIndex++;
return post;
},
Dzięki temu możemy zredukować ilość pól o jakich trzeba pamiętać i możemy używać tego w wielu miejscach np.: dodawanie nowego elementu i jego edycja może wymagać tych samych pól więc nie musimy powielać ich wszystkich tylko użyć odpowiedniego typu.