Link

Motivácia

Nemôžeme našu aplikáciu odizolovať od zvyšku sveta. Potrebujeme komunikovať s cudzími službami. Spôsoby akými sme to umožnili v minulosti sú rôzne (Twitter API, Github API). GraphQL to zjednocuje a berie o úroveň vyššie.

Dokument o vzniku GraphQL: GraphQL: The Documentary

Získavanie informácií z cudzích GraphQL APIs

Existujú APIs vytvorené priamo len na GraphQL, ale existujú aj “proxies”, ktoré obaľujú existujúce APIs. Vyhneme sa uzatvoreným a pozrieme sa na niektoré z otvorených: APIs-guru/graphql-apis

Na hranie použijeme GraphQL Hub Playground.

Skúsime získať informácie o používateľovi redditu:

{
  reddit {
    user(username: "GovSchwarzenegger") {
      username
      commentKarma
      createdISO
    }
}

… a môžeme nick skúsiť zameniť za “Here_Comes_The_King”.

My máme ale veľmi VEĽMI radi mapy a spolu s ďalšími ich hľadáme a zbierame a preto ideme nájsť niečo o nich.

{
  reddit {
    subreddit(name: "MapPorn"){
      hotListings(limit: 5) {
        title
        url
        score
        comments(limit: 3) {
          body
          author { 
            username
            commentKarma
          }
        }
      }
    }
  }
}

A môžeme sa ešte pohrať s niečím iným.

Získavanie informácií do Reactu z cudzích GraphQL APIs

Appka s mapami je TOP a naposledy sme robili React.

npx create-react-app hot-maps
cd hot-maps
npm start

Potrebujeme ešte knižnicu na prácu so serverom: npm install urql graphql.

Môžeme si vytvoriť klienta čo nás “napojí na server” vo všetký komponentoch nižšie.

const client = createClient({
  url: 'https://www.graphqlhub.com/graphql',
});

function App() {
  return (
    <Provider value={client}>
      <div className="App">
        <header className="App-header">
          <h1>These are the hottest maps</h1>
          <Maps />
        </header>
      </div>
    </Provider>
  );
}

A vytvoríme nový komponent Maps, ktorý bude robiť výber dát a zobrazí ich:

import React from 'react';
import { useQuery } from 'urql';

export default function Maps () {
    const [result] = useQuery({
        query: `{
            reddit {
              subreddit(name: "MapPorn"){
                hotListings(limit: 5) {
                  title
                  url
                  score
                  comments(limit: 3) {
                    body
                    author { 
                      username
                      commentKarma
                    }
                  }
                }
              }
            }
        }`,
    });

    const { fetching, data } = result;
    const maps =
        data
        ? data.reddit.subreddit.hotListings
        : [];

    const mapsList = maps.map(map => (
        <div>
            <h3>{map.title}</h3>
            <img src={map.url} alt={map.title} width="50%" />
            <p>Score: {map.score}</p>
            <hr />
        </div>
    ));

    return (
        <div>
            {fetching ? 'loading...' : mapsList}
        </div>
    );
}

Vlastné GraphQL API

GraphQL API nemusíme len konzumovať ale môžeme aj vytvoriť pre naše potreby (alebo druhých). Môžeme zostať v priečinku s react aplikáciou a vytvoríme v ňom aj server.

Na to potrebujeme zopár balíkov: npm install graphql express express-graphql cors.

Základ servera je:

const express = require('express');
const express_graphql = require('express-graphql');
const { buildSchema } = require('graphql');
const cors = require('cors');

const schema = buildSchema(`
    type Query {
        message: String
    }
`);
const root = {
    message: () => 'Hello World!'
};
const app = express();
app.use(cors());

app.use('/graphql', express_graphql({
    schema: schema,
    rootValue: root,
    graphiql: true
}));

app.listen(
    4000,
    () => console.log('Express GraphQL Server Now Running On localhost:4000/graphql'),
);

A spustíme ho pomocou node server.js. Môžeme otvoriť localhost:4000/graphql.

Na našom serveri sa možeme dostať k hodnotám rôzne, napr. aj získaním z iného GraphQL servera. Na to chceme vytvoriť klienta s balíčkom, ktorý si nainštalujeme: npm install graphql-request.

Na server pridáme type Map a resolver na maps.

const schema = buildSchema(`
    type Map {
        title: String!
        url: String!
        score: Int!
    }

    type Query {
        message: String
        maps: [Map!]!
    }
`);
    maps: async () => {
        const query = `{
            reddit {
              subreddit(name: "MapPorn") {
                hotListings(limit: 5) {
                  title
                  url
                  score
                }
              }
            }
        }`;

        const data = await request('https://www.graphqlhub.com/graphql', query);

        return data.reddit.subreddit.hotListings;
    },

A klienta upravíme podľa toho. Finálny kód v repozitári.

Ďalšie úlohy (na doma?)

  1. Skúste iné API zo zoznamu, ktoré vás zaujíma a má možnosť odkskúšania v prehliadači a napíšte zopár queries na čítanie dát.
  2. Doplnte na server do schémy a resolvera komentáre.
  3. Pridajte zobrazovanie komentárov na klienta.