{"id":15372,"date":"2022-08-10T15:12:53","date_gmt":"2022-08-10T13:12:53","guid":{"rendered":"https:\/\/www.centigrade.de\/?post_type=blog&#038;p=15372"},"modified":"2022-08-11T14:36:35","modified_gmt":"2022-08-11T12:36:35","slug":"graphql-net-und-react-miteinander-verbinden-teil-iv-react-und-graphql-schnell-zusammenbringen-dank-apollo-client","status":"publish","type":"blog","link":"https:\/\/www.centigrade.de\/de\/blog\/graphql-net-und-react-miteinander-verbinden-teil-iv-react-und-graphql-schnell-zusammenbringen-dank-apollo-client\/","title":{"rendered":"GraphQL, .Net und React miteinander verbinden \u2013 Teil IV: React und GraphQL schnell zusammenbringen dank Apollo Client"},"content":{"rendered":"\r\n<p>Hallo! \ud83d\ude42 Ich bin Ulrike, Medieninformatik-Studentin im Master und momentan Praktikantin bei Centigrade. W\u00e4hrend meines Praxissemesters durfte ich unter anderem gemeinsam mit <a href=\"https:\/\/www.centigrade.de\/de\/unternehmen\/team#mikhail.shabanov\">Mikhail<\/a> die VedaVersum-App fertigstellen. Wir wollten die Anwendung mit .NET, GraphQL und React als eine Art Wissensdatenbank bauen, in der sich Teammitglieder anmelden und Artikel verfassen, bearbeiten und l\u00f6schen k\u00f6nnen (s. <a href=\"https:\/\/www.centigrade.de\/de\/blog\/wie-man-graphql-net-und-react-miteinander-verbindet-teil-i\/\">Blog-Beitrag<\/a>). In diesem Teil der Beitragsserie m\u00f6chte ich mein Vorgehen bei der Anbindung des Frontends mit euch teilen und kurz berichten, wie es mir als React- und GraphQL-Neuling dabei ergangen ist.<!--more--><\/p>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading\">R\u00fcckblick: .NET, GraphQL und MongoDB<\/h2>\r\n\r\n\r\n\r\n<p>Im <a href=\"https:\/\/www.centigrade.de\/de\/blog\/wie-man-graphql-net-und-react-miteinander-verbindet-teil-i\/\">ersten Blog-Beitrag<\/a> hat euch Mikhail gezeigt, wie man eine GraphQL-API mit .Net erstellt und zur Unterst\u00fctzung <a href=\"https:\/\/chillicream.com\/docs\/hotchocolate\">Hot Chocolate<\/a> von <a href=\"https:\/\/chillicream.com\/\">ChilliCream<\/a> als GraphQL Server gew\u00e4hlt. Das von ChilliCream mitgelieferte Hilfsprogramm <a href=\"https:\/\/chillicream.com\/docs\/bananacakepop\">Banana Cake Pop<\/a> zum \u00dcberpr\u00fcfen von GraphQL-Anfragen wird uns auch sp\u00e4ter noch von Nutzen sein, wenn wir unsere Anfragen vom Frontend isoliert testen. Im <a href=\"https:\/\/www.centigrade.de\/de\/blog\/how-to-engage-graphql-net-and-react-together-part-ii-veda-versum-backend-authentication\/\">Folgebeitrag<\/a> haben wir uns ganz auf die Backend-Authentifizierung am Beispiel von GitLab konzentriert und im <a href=\"https:\/\/www.centigrade.de\/de\/blog\/graphql-net-und-react-miteinander-verbinden-teil-iii-veda-versum-backend-authentication\/\">letzten Beitrag<\/a> f\u00fcr die Gew\u00e4hrleistung der Datenpersistenz MongoDB zum Backend hinzugef\u00fcgt.<\/p>\r\n\r\n\r\n\r\n<p>In diesem Beitrag werden wir GraphQL-Anfragen in JavaScript schreiben und diese mittels der Apollo Client Library in unser React-Frontend integrieren.<\/p>\r\n\r\n\r\n\r\n<p>Ein wichtiger Hinweis zum Code auf <a href=\"https:\/\/github.com\/Centigrade\/vedaversum\">Github<\/a>: W\u00e4hrend wir an dieser Beitragsserie f\u00fcr unseren Blog schreiben, wurde und wird an VedaVersum weitergearbeitet. Dementsprechend gibt es \u2013 wie meistens beim Entwickeln von Software \u2013 immer wieder gr\u00f6\u00dfere und kleinere Umbauten und Umbenennungen. Beispielsweise wurde inzwischen die <em>VedaVersumCard <\/em>zum <em>VedaVersumArticle.<\/em><\/p>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading\">Frontend mit React, Tailwind CSS und Apollo Client<\/h2>\r\n\r\n\r\n\r\n<p>F\u00fcr die Implementierung des Frontends verwenden wir folgende Technologien:<\/p>\r\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-15382\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Logos.png\" alt=\"Logos React, tailwind, apollo\" width=\"682\" height=\"109\" srcset=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Logos.png 682w, https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Logos-300x48.png 300w\" sizes=\"auto, (max-width: 682px) 100vw, 682px\" \/><\/p>\r\n\r\n\r\n\r\n<p>Wie schon im <a href=\"https:\/\/www.centigrade.de\/de\/blog\/wie-man-graphql-net-und-react-miteinander-verbindet-teil-i\/\">ersten Blog-Beitrag<\/a> ausf\u00fchrlich beschrieben, haben wir uns f\u00fcr <a href=\"https:\/\/reactjs.org\/\"><strong>React<\/strong><\/a> entschieden, weil es leichtgewichtiger (User Interface <em>Library<\/em>) ist als Angular (User Interface <em>Framework<\/em>).<\/p>\r\n\r\n\r\n\r\n<p><a href=\"https:\/\/tailwindcss.com\/\"><strong>Tailwind CSS<\/strong><\/a> ist ein CSS-Framework, das den \u201eUtility first\u201c-Ansatz verfolgt. Den Ansto\u00df, uns mit diesem Thema auseinander zu setzen, gab uns ein <a href=\"https:\/\/frontstuff.io\/in-defense-of-utility-first-css\">Blogartikel<\/a> von <a href=\"https:\/\/frontstuff.io\/\">frontstuff.io<\/a>. Wir haben uns aus folgenden Gr\u00fcnden f\u00fcr TailwindCSS entschieden: F\u00fcr unsere kleine Anwendung wollten wir nichts Schwergewichtiges wie z. B. Bootstrap. Zus\u00e4tzlich werden die Anforderungen an unsere Anwendung und damit auch ihr Design und Layout kontinuierlich \u00fcberarbeitet. Mit Tailwind CSS ist es m\u00f6glich, diese \u00c4nderungen schnell direkt in HTML umzusetzen.<br \/>Da eine ausf\u00fchrliche Er\u00f6rterung des Frameworks und \u201eUtility first\u201c den Umfang des Blogbeitrags sprengen w\u00fcrde, gehe ich nur der Vollst\u00e4ndigkeit halber kurz darauf ein.<\/p>\r\n\r\n\r\n\r\n<p><a href=\"https:\/\/www.apollographql.com\/apollo-client\/\"><strong>Apollo Client<\/strong><\/a> ist eine open source JavaScript Library f\u00fcr die Datenverwaltung mit GraphQL. Wir haben f\u00fcr unser Projekt diese Library gew\u00e4hlt, weil Apollo Client h\u00e4ufig eingesetzt wird, gut dokumentiert ist und sehr viel Logik selbstst\u00e4ndig \u201eabarbeitet\u201c. Beispielsweise m\u00fcssen Fehler bei der Datenabfrage nicht manuell implementiert werden, sondern Apollo Client sendet sie direkt mit und wir m\u00fcssen uns nur noch darum k\u00fcmmern, was im Fehlerfall passieren soll.<\/p>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading\">VedaVersum \u2013 Eine React-Anwendung, die \u00fcber Apollo Client mit dem GraphQL-Backend kommuniziert<\/h2>\r\n\r\n\r\n\r\n<p>Nachdem wir die Anforderungen an die VedaVersum-App f\u00fcr die Ver\u00f6ffentlichung des Blog-Beitrags noch einmal \u00fcberarbeitet haben, enth\u00e4lt die fertige Anwendung im ersten \u201e<a href=\"https:\/\/de.wikipedia.org\/wiki\/Minimum_Viable_Product\">Minimum Viable Product<\/a>\u201c folgende Features:<\/p>\r\n\r\n\r\n\r\n<ul class=\"wp-block-list\">\r\n<li>Auf der Startseite wird mir eine Liste mit allen existierenden Artikeln angezeigt. Diese Liste kann ich als Benutzer*in nach den von mir erstellten Artikeln filtern. Daf\u00fcr ben\u00f6tigen wir <strong><em>GraphQL Queries<\/em><\/strong>.<\/li>\r\n<li>Ich kann Artikel anlegen, von mir erstellte Artikel l\u00f6schen und sowohl Artikel, die ich verfasst habe, als auch die Artikel von anderen Benutzer*innen bearbeiten. Daf\u00fcr ben\u00f6tigen wir <strong><em>GraphQL Mutations<\/em><\/strong>.<\/li>\r\n<li>Legen andere Benutzer*innen neue Artikel an oder bearbeiten bestehende Artikel, w\u00e4hrend ich eingeloggt bin, werde ich vom System benachrichtigt. Daf\u00fcr ben\u00f6tigen wir eine <strong><em>GraphQL Subscription<\/em><\/strong>.<\/li>\r\n<\/ul>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading\">Apollo Client in React initialisieren<\/h2>\r\n\r\n\r\n\r\n<p>In den <a href=\"https:\/\/www.apollographql.com\/docs\/react\/get-started\/\">Apollo Client Docs<\/a> ist sehr gut beschrieben, wie man Apollo Client in ein React-Projekt integriert. Da wir allerdings in den vorherigen Blogbeitr\u00e4gen die Authentifizierung implementiert haben, ben\u00f6tigen wir etwas mehr Code f\u00fcr die Initialisierung als das \u201eGet started\u201c von den Docs. Dementsprechend haben wir diesen Code in eine eigene Datei namens \u201eApolloSetup.ts\u201c ausgelagert. Den dort angelegten Apollo Client importieren wir in der \u201eindex.tsx\u201c-Datei und legen ihn um unsere Anwendung herum. Das Ger\u00fcst sieht dann folgenderma\u00dfen aus:<\/p>\r\n\r\n\r\n\r\n<p><em>ApolloSetup.ts<\/em><\/p>\r\n\r\n\r\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nexport const apolloClient = new ApolloClient({\r\n  ...\r\n});\r\n\r\n<\/pre><\/div>\r\n\r\n\r\n<p>&nbsp;<\/p>\r\n\r\n\r\n\r\n<p><em><br \/>index.tsx<\/em><\/p>\r\n\r\n\r\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nconst root = ReactDOM.createRoot(document.getElementById(&#039;root&#039;) as HTMLElement);\r\n\r\nroot.render(\r\n  &lt;ApolloProvider client={apolloClient}&gt;\r\n    ...\r\n  &lt;\/ApolloProvider&gt;,\r\n);\r\n\r\n<\/pre><\/div>\r\n\r\n\r\n<p><strong><br \/><\/strong>Die grundlegende Implementierung von GraphQL Queries, Mutations und Subscriptions ist sehr \u00e4hnlich zueinander. Daher werde ich im folgenden Abschnitt GraphQL Queries etwas ausf\u00fchrlicher beschreiben und die Erkl\u00e4rung in den weiteren Abschnitten kurz halten.<\/p>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading\">Wie man GraphQL-Queries schreibt und mithilfe von Apollo Client im React-Frontend verwendet<\/h2>\r\n\r\n\r\n\r\n<p>GraphQL Queries werden dazu verwendet, Daten aus der Datenbank auszulesen, weshalb wir sie oft in unserer Anwendung benutzen. Diese Queries k\u00f6nnen zum einen direkt aufgerufen werden, beispielsweise um alle in der Datenbank gespeicherten Artikel abzufragen. Zum anderen kann man ihnen Parameter \u00fcbergeben, z. B. um alle gespeicherten Artikel nach den Artikeln des eingeloggten Users zu filtern.<\/p>\r\n\r\n\r\n\r\n<p><em><u>GraphQL Queries in JavaScript schreiben<\/u><\/em><\/p>\r\n\r\n\r\n\r\n<p>Um in JavaScript eine Query als GraphQL-Query zu definieren, muss man das Schl\u00fcsselwort <em>gql<\/em> mit Backticks ( ` ` ) verwenden. Zwischen die Backticks schreibt man die Query und speichert den gesamten Ausdruck in einer Konstante:<\/p>\r\n\r\n\r\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nexport const ALL_ARTICLES_QUERY = gql`\r\n   ...\r\n`;\r\n\r\n<\/pre><\/div>\r\n\r\n\r\n<p>Die GraphQL Query selbst sieht dann folgenderma\u00dfen aus: Eingeleitet durch das Schl\u00fcsselwort <em>query<\/em> und dem Namen der Query, packt man in geschweifte Klammern die Datenbank-Abfrage. Wichtig ist, dass die GraphQL Query genauso benannt wird wie die Variable, in der im Backend das Ergebnis der Anfrage gespeichert wird. Ansonsten kann das Ergebnis der Datenbank-Abfrage nicht zugeordnet werden und man bekommt eine Fehlermeldung. Wie genau man eine GraphQL Query schreibt, ist in den <a href=\"https:\/\/graphql.org\/learn\/queries\/\">GraphQL Docs<\/a> sehr gut beschrieben.<\/p>\r\n\r\n\r\n\r\n<p>Unsere Query, die alle Informationen aller in der Datenbank gespeicherten Artikel ausliest, sieht als fertige Konstante dann so aus:<\/p>\r\n\r\n\r\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nexport const ALL_ARTICLES_QUERY = gql`\r\n  query GetAllArticles {\r\n    allArticles {\r\n      id\r\n      title\r\n      content\r\n      created\r\n      userCreated\r\n      relatedArticleIds\r\n      userUpdated\r\n      updatedAt\r\n      accessCounter\r\n    }\r\n  }\r\n`;\r\n\r\n<\/pre><\/div>\r\n\r\n\r\n<p>Um sicherzugehen, dass die GraphQL Query an sich ausf\u00fchrbar ist und das Backend das gew\u00fcnschte Ergebnis zur\u00fcckgibt, k\u00f6nnen wir die Anfrage auch ohne Frontend in Banana Cake Pop testen. Dazu kopieren wir einfach die reine GraphQL Query aus dem Code und f\u00fcgen sie in Banana Cake Pop ein (s. auch <a href=\"https:\/\/www.centigrade.de\/de\/blog\/wie-man-graphql-net-und-react-miteinander-verbindet-teil-i\/\">erster Blog-Beitrag<\/a>). Gibt es in der Query einen Syntaxfehler, weist uns das Programm gl\u00fccklicherweise sofort darauf hin. Ist die Query korrekt, zeigt uns Banana Cake Pop das Ergebnis vom Backend:<\/p>\r\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-15384\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Gif1-Query.gif\" alt=\"Banana Cake Pop Ergebnis Backend\" width=\"1920\" height=\"1080\" \/><\/p>\r\n\r\n\r\n\r\n<p><em><u>GraphQL Queries mit Apollo Client in React verwenden<\/u><\/em><\/p>\r\n\r\n\r\n\r\n<p>Um jetzt die GraphQL Query in unserer React Anwendung auszuf\u00fchren, m\u00fcssen wir zun\u00e4chst den React Hook <em>useQuery <\/em>von Apollo Client importieren. Dann legen wir eine Konstante an, in die das Ergebnis unserer GraphQL Query gespeichert wird. Wir wissen, dass Datenbankabfragen nicht immer erfolgreich aufgel\u00f6st werden k\u00f6nnen, z. B. wenn der Server, auf dem die Daten liegen, gerade nicht erreichbar ist. Genauso kann es sein, dass die Bearbeitung der Anfrage l\u00e4nger dauert. Um eine gute Usability zu erm\u00f6glichen, m\u00f6chten wir beide F\u00e4lle abdecken, und w\u00e4hlen daher folgende Schreibweise:<\/p>\r\n\r\n\r\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nconst {\r\n    error: errorAllArticles,\r\n    data: allArticlesData,\r\n    loading: loadingAllArticles,\r\n  } = ...\r\n\r\n<\/pre><\/div>\r\n\r\n\r\n<p>Wird die Query erfolgreich aufgel\u00f6st, werden die Daten in die data-Variable (hier umbenannt in \u201eallArticlesData\u201c) gespeichert. Sp\u00e4ter k\u00f6nnen wir das Ergebnis im JavaScript Code weiterverarbeiten oder im HTML-Bereich abfragen und die entsprechende UI-Komponente anzeigen.<\/p>\r\n\r\n\r\n\r\n<p>Aber zur\u00fcck zur Query \u2013 um die Query aufzurufen, weisen wir unsere Konstante nun als \u201eWert\u201c folgenden Ausdruck zu:<\/p>\r\n\r\n\r\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nconst { ... } = useQuery(ALL_ARTICLES_QUERY);\r\n<\/pre><\/div>\r\n\r\n\r\n<p><em>useQuery<\/em> \u00fcbergeben wir in runden Klammern die Parameter, die die Query ben\u00f6tigt \u2013 in diesem Fall nur den Namen der GraphQL Query, die wir ausf\u00fchren m\u00f6chten. Die GraphQL Query muss dazu importiert werden.<\/p>\r\n\r\n\r\n\r\n<p>Allgemein kann man <em>useQuery<\/em> au\u00dfer dem Namen weitere Parameter \u00fcbergeben. Diese werden in einem Objekt \u201egesammelt\u201c und mit einem Komma getrennt nach dem Namen der GraphQL Query mitgesendet. Ein Beispiel daf\u00fcr ist <em>fetchPolicy<\/em>, dessen Wert angibt, ob und wie Daten gecached werden. Bei GraphQL Queries, die \u00dcbergabeparameter erwarten, werden die Variablen ebenfalls hier aufgelistet. Aber das schauen wir uns im Folgenden genauer an:<\/p>\r\n\r\n\r\n\r\n<p><em><u>GraphQL Queries mit Parametern in JavaScript schreiben<\/u><\/em><\/p>\r\n\r\n\r\n\r\n<p>GraphQL Queries k\u00f6nnen Parameter erwarten. Das k\u00f6nnen wir uns beispielsweise zu Nutze machen, wenn wir einen Artikel lesen wollen. Benutzer*innen gehen nicht immer den Umweg \u00fcber die Startseite, sondern speichern sich einen Artikel z. B. als Lesezeichen im Browser ab. In diesem Fall m\u00f6chten wir nicht alle Artikel von der Datenbank anfordern, sondern direkt nur die Informationen des ausgew\u00e4hlten Artikels. Dazu schreiben wir eine GraphQL Query, die die ID eines Artikels bekommt und dann alle Datenbankeintr\u00e4ge zu genau diesem Artikel zur\u00fcckgibt \u2013 vorausgesetzt der Artikel existiert. Das Ganze sieht am Ende so aus:<\/p>\r\n\r\n\r\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nexport const ARTICLE_BY_ID_QUERY = gql`\r\n  query GetArticle($articleId: String!) {\r\n    article(articleId: $articleId) {\r\n      # database table fields\r\n    }\r\n  }\r\n`;\r\n\r\n<\/pre><\/div>\r\n\r\n\r\n<p>Die GraphQL Query erwartet eine Artikel-ID vom Typ String, die sie in der n\u00e4chsten Zeile ans Backend weiterreicht. Wichtig dabei ist, dass die Namen der Parameter, die die GraphQL Query bekommt, mit einem Dollar-Zeichen beginnen und auch genauso weitergegeben werden m\u00fcssen.<\/p>\r\n\r\n\r\n\r\n<p>Zum Testen k\u00f6nnen wir auch diese GraphQL Query in Banana Cake Pop mit der Artikel-ID eines unserer gespeicherten Artikel ausf\u00fchren. Dabei m\u00fcssen wir die Artikel-ID nicht der GraphQL Query, sondern direkt der Backend-Funktion \u00fcbergeben:<\/p>\r\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-15386\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Gif2-QueryWithParameters.gif\" alt=\"Query With Parameters\" width=\"1920\" height=\"1080\" \/><\/p>\r\n\r\n\r\n\r\n<p>Um diese GraphQL Query erfolgreich im Frontend auszuf\u00fchren, m\u00fcssen wir bei den Parametern von <em>useQuery<\/em> ein Objekt mit dem Feld \u201evariables\u201c hinzuf\u00fcgen. Dieses Feld bekommt ebenfalls ein Objekt, in dem wir bei mehreren \u00dcbergabeparametern alle auflisten w\u00fcrden. Damit GraphQL die \u00fcbergebenen Werte verarbeiten kann, m\u00fcssen die Felder des \u201evariables\u201c-Objekts genau gleich hei\u00dfen wie die Parameter, die die Query erwartet. In diesem Fall haben wir als Parameter nur die Artikel-ID, die wir zuvor als \u201ecurrentArticleId\u201c gespeichert haben. Von der <em>useQuery<\/em>-Struktur her bleibt der Rest gleich:<\/p>\r\n\r\n\r\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nconst { error, data, loading } = useQuery(ARTICLE_BY_ID_QUERY, {\r\n    variables: { articleId: currentArticleId },\r\n  });\r\n\r\n<\/pre><\/div>\r\n\r\n\r\n<h2 class=\"wp-block-heading\">Wie man GraphQL-Mutations schreibt und mithilfe von Apollo Client im React-Frontend verwendet<\/h2>\r\n\r\n\r\n\r\n<p>GraphQL Mutations verwendet man, um Daten in der Datenbank hinzuzuf\u00fcgen, zu \u00e4ndern oder zu l\u00f6schen. Da unsere Benutzer*innen genau das tun k\u00f6nnen, brauchen wir f\u00fcr jede Aktion eine Mutation. Die Mutations haben zwar unterschiedliche Parameter, sind aber ansonsten gleich aufgebaut. Wir schauen uns das Ganze anhand der \u201eUpdateArticle\u201c Mutation an.<\/p>\r\n\r\n\r\n\r\n<p><em><u>GraphQL Mutations in JavaScript schreiben<\/u><\/em><\/p>\r\n\r\n\r\n\r\n<p>Die Grundstruktur eine GraphQL Mutation in JavaScript ist die Gleiche wie bei einer GraphQL Query:<\/p>\r\n\r\n\r\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nexport const UPDATE_ARTICLE_MUTATION = gql`\r\n  mutation UpdateArticle($articleId: String!, $articleTitle: String!, $articleContent: String!) {\r\n    articleAction(action: UPDATE, articleId: $articleId, title: $articleTitle, content: $articleContent) {\r\n      # database table fields\r\n    }\r\n  }\r\n`;\r\n\r\n<\/pre><\/div>\r\n\r\n\r\n<p>Zwei kleine Unterschiede gibt es: Da wir eine Mutation angelegt haben, verwenden wir als Schl\u00fcsselwort auch <em>mutation <\/em>statt <em>query<\/em>. Au\u00dferdem haben wir im Backend eine Funktion geschrieben haben, die alle Artikel-Mutations (anlegen \u2013 \u201eCREATE\u201c, bearbeiten \u2013 \u201eUPDATE\u201c, l\u00f6schen \u2013 \u201eDELETE\u201c) abfertigt. Dementsprechend m\u00fcssen wir beim Aufruf dieser Funktion die \u201eaction\u201c als zus\u00e4tzlichen Parameter \u00fcbergeben \u2013 bei \u201eUpdateArticle\u201c nat\u00fcrlich \u201eUPDATE\u201c.<\/p>\r\n\r\n\r\n\r\n<p>Mutations kann man wie GraphQL Queries mit \u00dcbergabeparametern in Banana Cake Pop testen:<\/p>\r\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-15388\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Gif3-Mutation.gif\" alt=\"Mutation Test Banana Cake Pop\" width=\"1920\" height=\"1080\" \/><\/p>\r\n\r\n\r\n\r\n<p><em><u>GraphQL Mutations mit Apollo Client in React verwenden<\/u><\/em><\/p>\r\n\r\n\r\n\r\n<p>GraphQL Mutations werden in React wieder \u00fcber einen React Hook von Apollo Client eingebunden, und zwar mittels <em>useMutation<\/em>. Die Grundstruktur deckt sich mit der einer Query. Aber im Detail unterscheiden sie sich:<\/p>\r\n\r\n\r\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nconst &#x5B;updateArticle] = useMutation(UPDATE_ARTICLE_MUTATION, {\r\n    variables: { articleId: articleData?.id, articleTitle: title, articleContent: content },\r\n    onError: error =&gt; {\r\n      \/\/ error handling\r\n    },\r\n    onCompleted: data =&gt; {\r\n      \/\/ actions when successful\r\n    },\r\n  });\r\n\r\n<\/pre><\/div>\r\n\r\n\r\n<p>Die verschiedenen Responses (Error, Data, Loading) werden nicht in der Konstante aufgef\u00fchrt, sondern in der Mutation selbst. Sie werden nach dem Namen der Mutation und den \u00dcbergabeparametern als <em>onError<\/em> bzw. <em>onCompleted<\/em> mit den dazugeh\u00f6rigen Anweisungen aufgelistet.<\/p>\r\n\r\n\r\n\r\n<p>Sp\u00e4ter im Code kann die Mutation wie eine normale Funktion aufgerufen werden:<\/p>\r\n\r\n\r\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nif (editorSettings.type === &#039;create&#039;) {\r\n   insertArticle();\r\n} else if (editorSettings.type === &#039;edit&#039;) {\r\n   updateArticle();\r\n}\r\n\r\n<\/pre><\/div>\r\n\r\n\r\n<h2 class=\"wp-block-heading\">Wie man GraphQL-Subscriptions schreibt und mithilfe von Apollo Client im React-Frontend verwendet<\/h2>\r\n\r\n\r\n\r\n<p>GraphQL Subscriptions kommen zum Einsatz, wenn ein Client Nachrichten in Echtzeit vom Server erhalten soll. Wie Mikhail im <a href=\"https:\/\/www.centigrade.de\/de\/blog\/wie-man-graphql-net-und-react-miteinander-verbindet-teil-i\/\">ersten Blog-Beitrag<\/a> schon erw\u00e4hnt hat, sind Subscriptions eines DER Features von GraphQL. Was ich bisher zu GraphQL Queries und Mutations geschrieben habe, klingt im ersten Moment sehr nach Standard <a href=\"https:\/\/de.wikipedia.org\/wiki\/Representational_State_Transfer\">REST<\/a> GET- und POST-Befehlen. GraphQL setzt diese mit normalen HTTP-Methoden um. Bei Subscriptions sieht das allerdings anders aus: Auch wenn man oberfl\u00e4chlich betrachtet nichts davon mitbekommt, arbeitet GraphQL bei <em>Subscriptions<\/em> mit Websockets. Deswegen m\u00fcssen wir sp\u00e4ter f\u00fcr Apollo Client auch noch die entsprechende Library in unser Projekt integrieren. Der Anwendungsfall f\u00fcr eine Subscription bei VedaVersum sind die Benachrichtigungen, die serverseitig ausgel\u00f6st werden sollen: Legt jemand einen neuen Artikel an oder bearbeitet einen gespeicherten Artikel, bekommen alle eingeloggten Benutzer*innen eine Benachrichtigung und k\u00f6nnen sich die entsprechenden Artikel direkt anzeigen lassen.<\/p>\r\n\r\n\r\n\r\n<p><em><u>GraphQL Subscriptions in JavaScript schreiben<\/u><\/em><\/p>\r\n\r\n\r\n\r\n<p>Eine GraphQL Subscription in JavaScript ist genauso aufgebaut wie eine GraphQL Query ohne Parameter:<\/p>\r\n\r\n\r\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nexport const ARTICLE_CHANGED_SUBSCRIPTION = gql`\r\n  subscription OnArticleChanged {\r\n    articleChanged {\r\n      action\r\n      vedaVersumArticle {\r\n        # database table fields\r\n      }\r\n    }\r\n  }\r\n`;\r\n\r\n<\/pre><\/div>\r\n\r\n\r\n<p>Als Schl\u00fcsselwort schreiben wir hier <em>subscription <\/em>statt<em> query<\/em>.<\/p>\r\n\r\n\r\n\r\n<p>Eine Subscription in Banana Cake Pop zu testen ist etwas komplizierter als eine Query oder Mutation:<\/p>\r\n\r\n\r\n\r\n<ol class=\"wp-block-list\">\r\n<li>Wir starten in einem Tab die Subscription. Ob die Subscription aktiv ist, sehen wir an dem Button, \u00fcber den wir GraphQL Anweisungen ausf\u00fchren. Wo vorher \u201eRun\u201c mit einem Pfeil-Icon stand, sollte jetzt \u201eCancel\u201c und ein Ladekreis angezeigt werden.<\/li>\r\n<li>Wir wechseln in einen zweiten Tab, authentifizieren uns und bearbeiten einen Artikel.<\/li>\r\n<li>Wir gehen zur\u00fcck zum ersten Tab. Dort sollte uns im rechten Feld der ge\u00e4nderte Artikel mit der \u201eaction\u201c, die ausgef\u00fchrt wurde, angezeigt werden.<\/li>\r\n<\/ol>\r\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-15390\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Gif4-Subscription.gif\" alt=\"GraphQL Subscriptions mit Apollo Client in React verwenden\" width=\"1920\" height=\"1080\" \/><\/p>\r\n\r\n\r\n\r\n<p><em><u>GraphQL Subscriptions mit Apollo Client in React verwenden<\/u><\/em><\/p>\r\n\r\n\r\n\r\n<p>Bevor wir unsere Subscription in React verwenden k\u00f6nnen, ben\u00f6tigen wir zun\u00e4chst eine Subscription Library. Auch wenn es in den <a href=\"https:\/\/www.apollographql.com\/docs\/react\/data\/subscriptions\">Apollo Docs<\/a> nicht empfohlen wird, m\u00fcssen wir die veraltete Library <em>subscription-transport-ws <\/em>nehmen. Grund daf\u00fcr ist, dass Hot Chocolate, unser GraphQL Server, die Nachfolger-Library <em>graphql-ws<\/em> noch nicht unterst\u00fctzt. Wie genau ihr die Library in eurem Projekt integriert, ist <a href=\"https:\/\/www.apollographql.com\/docs\/react\/data\/subscriptions#the-older-subscriptions-transport-ws-library\">am Ende des Apollo Docs Eintrags<\/a> ausf\u00fchrlich beschrieben.<\/p>\r\n\r\n\r\n\r\n<p>Wenn ihr die Library erfolgreich eingerichtet habt, k\u00f6nnt ihr im Code den React Hook <em>useSubscription<\/em> genauso wie<em> useQuery <\/em>ohne Parameter verwenden:<\/p>\r\n\r\n\r\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nconst { data: subscriptionData } = useSubscription(ARTICLE_CHANGED_SUBSCRIPTION);\r\n<\/pre><\/div>\r\n\r\n\r\n<p>Jetzt bekommt der Client jedes Mal eine Benachrichtigung vom Server, wenn ein neuer Artikel angelegt oder ein bestehender Artikel bearbeitet oder gel\u00f6scht wurde. So weit, so gut. Nur nutzt uns das bisher noch nichts. Die Idee war, dass Benutzer*innen eine Benachrichtigung bekommen, wenn die Artikel-Tabelle in der Datenbank ge\u00e4ndert wurde. Um das zu erreichen, m\u00fcssen wir mithilfe des React Hooks <em>useEffect<\/em> die Daten, die die Subscription sendet (hier \u201esubscriptionData\u201c), \u00fcberwachen. Sobald sie sich \u00e4ndern, also der Client vom Server einen \u201eneuen\u201c ge\u00e4nderten Artikel erh\u00e4lt, werden die Anweisungen innerhalb des <em>useEffect<\/em> Hooks ausgef\u00fchrt. Im Code sieht das vereinfacht so aus:<\/p>\r\n\r\n\r\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nuseEffect(() =&gt; {\r\n    if (subscriptionData) {\r\n      \/\/ instructions what to do every time\r\n      \/\/ a new change is sent by the server\r\n    }\r\n  }, &#x5B;subscriptionData]);\r\n\r\n<\/pre><\/div>\r\n\r\n\r\n<p>In den Abh\u00e4ngigkeits-Array am Ende schreiben wir sp\u00e4ter alle Variablen oder Funktionen, von denen die Anweisungen innerhalb der geschweiften Klammern abh\u00e4ngen. Jetzt m\u00fcssen wir nur noch in der if-Abfrage die User-Benachrichtigungen programmieren, dann ist auch dieses Feature fertig \ud83d\ude42<\/p>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading\">Fazit und Ausblick<\/h2>\r\n\r\n\r\n\r\n<p>In diesem Blogbeitrag habe ich euch von meinem Vorgehen und meinen Erfahrungen, wie man ein React-Frontend mithilfe von Apollo Client an ein GraphQL-Backend anbindet, berichtet. Wir haben gelernt, wof\u00fcr man GraphQL Queries, Mutations und Subscriptions verwendet und wie man sie in JavaScript im React-Frontend implementiert. Dazu geh\u00f6rte auch, wie man diese GraphQL-Anfragen mittels Apollo Client in React aufrufen und deren Ergebnis im Code weiterverarbeiten kann.<\/p>\r\n\r\n\r\n\r\n<p>Mir pers\u00f6nlich hat das Projekt viel Wissen vermittelt, weil React, GraphQL und \u201eutility-first\u201c alles Bereiche sind, in denen ich mich bisher wenig bis gar nicht bewegt habe. Im folgenden Abschnitt ziehe ich f\u00fcr jede verwendete Technologie ein kurzes Fazit.<\/p>\r\n\r\n\r\n\r\n<p><strong>React<\/strong> habe ich als nicht besonders einsteigerfreundlich empfunden \u2013 unter anderem, weil ich urspr\u00fcnglich von Vue.js komme, was sehr unterschiedlich zu React ist. Daher habe ich mir mit den Konzepten im Vergleich zum (parallelen) Einstieg in Angular eher schwergetan. Au\u00dferdem war es teilweise schwierig, L\u00f6sungen f\u00fcr Probleme oder Fehlermeldungen zu finden, weil viele Forenbeitr\u00e4ge etc. noch mit der \u00e4lteren Klassensyntax statt der neuen Funktionssyntax verfasst wurden.<\/p>\r\n\r\n\r\n\r\n<p>Mit <strong>Tailwind CSS<\/strong> konnte ich mich nur bedingt anfreunden. Ich verstehe den Gedanken, weniger CSS-Deklarationen zu schreiben, die sich dann in den Stylesheets auch weniger oft wiederholen. L\u00f6st man allerdings das komplette Styling \u00fcber die Utility-Klassen, erh\u00e4lt man sehr schnell sehr viele Klassennamen, die meiner Meinung nach den Code un\u00fcbersichtlich machen. Beispielsweise beschreibt im Code folgende <em>Zeile<\/em> das Styling f\u00fcr einen Button:<\/p>\r\n\r\n\r\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: css; title: ; notranslate\" title=\"\">\r\nclassName=&quot;hover:cursor-pointer outline outline-4 outline-transparent text-white text-base text-center rounded-lg font-white bg-primary py-2 px-3 mr-4 hover:outline-primary-light active:bg-primary-dark disabled:bg-primary-dark disabled:outline-transparent disabled:cursor-auto&quot;\r\n<\/pre><\/div>\r\n\r\n\r\n<p><strong>Apollo Client<\/strong> zu verwenden war ziemlich entspannt, da die Library gef\u00fchlt alles (Ladezustand, Fehler, etc.) abf\u00e4ngt und aufbereitet, sodass wir mit den Responses der Abfragen direkt weiterarbeiten konnten. Au\u00dferdem kann man viele Einstellungen, z.B. wie gecached wird, so definieren, wie es am besten zum Projekt passt. Ein gro\u00dfer Pluspunkt ist zus\u00e4tzlich, dass man Apollo Client auch als Einsteiger sehr schnell in Projekte integrieren und direkt damit arbeiten kann.<\/p>\r\n\r\n\r\n\r\n<p>Bei <strong>GraphQL<\/strong> war es sehr interessant, mal etwas anderes als SQL-Abfragen zu verwenden. Vor allem, weil die GraphQL-Anfragen zwar unter Umst\u00e4nden viel Schreibarbeit sind, aber man dadurch auch genau sieht, was man als Ergebnis der Anfrage zur\u00fcckbekommt. In diesem Projekt konnten wir leider nicht alle Features von GraphQL unterbringen, z. B. serverseitige Datenumwandlungen wie die Konvertierung von Einheiten, aber es war trotzdem spannend, sich damit zu besch\u00e4ftigen.<\/p>\r\n\r\n\r\n\r\n<p>So, jetzt haben wir eine lauff\u00e4hige Web-App, mit minimalen, aber funktionierenden Features. Um die Anwendung intern zu nutzen, fehlt eigentlich nur noch ein Deployment. Wir haben uns dazu entschieden, VedaVersum vorerst auf GitLab-Pages zu deployen. Wie genau man dabei vorgeht, zeigen euch unsere DevOps Engineers im n\u00e4chsten Artikel dieser Beitragsserie \ud83d\ude42<\/p>\r\n\r\n\r\n\r\n<p>Danke f\u00fcrs Lesen und happy Coding!<\/p>\r\n","protected":false},"author":70,"featured_media":0,"template":"","tags":[887,961,890,514,617,515],"class_list":["post-15372","blog","type-blog","status-publish","hentry","tag-net-de","tag-apollo","tag-graphql-de","tag-react","tag-ux-engineering","tag-web-engineering"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.centigrade.de\/de\/wp-json\/wp\/v2\/blog\/15372","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.centigrade.de\/de\/wp-json\/wp\/v2\/blog"}],"about":[{"href":"https:\/\/www.centigrade.de\/de\/wp-json\/wp\/v2\/types\/blog"}],"author":[{"embeddable":true,"href":"https:\/\/www.centigrade.de\/de\/wp-json\/wp\/v2\/users\/70"}],"version-history":[{"count":7,"href":"https:\/\/www.centigrade.de\/de\/wp-json\/wp\/v2\/blog\/15372\/revisions"}],"predecessor-version":[{"id":15403,"href":"https:\/\/www.centigrade.de\/de\/wp-json\/wp\/v2\/blog\/15372\/revisions\/15403"}],"wp:attachment":[{"href":"https:\/\/www.centigrade.de\/de\/wp-json\/wp\/v2\/media?parent=15372"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.centigrade.de\/de\/wp-json\/wp\/v2\/tags?post=15372"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}