Quellcode durchsuchen

Query pokemon index via Relay with Show fragment

Andrew Swistak vor 6 Jahren
Ursprung
Commit
f4725ea831

+ 173 - 0
app/javascript/packs/frontend/__generated__/IndexQuery.graphql.ts

@@ -0,0 +1,173 @@
+/* tslint:disable */
+
+import { ConcreteRequest } from "relay-runtime";
+import { Show_pokemon$ref } from "./Show_pokemon.graphql";
+export type IndexQueryVariables = {};
+export type IndexQueryResponse = {
+    readonly pokemonConnection: {
+        readonly edges: ReadonlyArray<{
+            readonly node: {
+                readonly id: string;
+                readonly " $fragmentRefs": Show_pokemon$ref;
+            } | null;
+        } | null> | null;
+    };
+};
+export type IndexQuery = {
+    readonly response: IndexQueryResponse;
+    readonly variables: IndexQueryVariables;
+};
+
+
+
+/*
+query IndexQuery {
+  pokemonConnection {
+    edges {
+      node {
+        id
+        ...Show_pokemon
+      }
+    }
+  }
+}
+
+fragment Show_pokemon on Pokemon {
+  id
+  iid
+  nickname
+  pokedexNumber
+}
+*/
+
+const node: ConcreteRequest = (function(){
+var v0 = {
+  "kind": "ScalarField",
+  "alias": null,
+  "name": "id",
+  "args": null,
+  "storageKey": null
+};
+return {
+  "kind": "Request",
+  "fragment": {
+    "kind": "Fragment",
+    "name": "IndexQuery",
+    "type": "Query",
+    "metadata": null,
+    "argumentDefinitions": [],
+    "selections": [
+      {
+        "kind": "LinkedField",
+        "alias": null,
+        "name": "pokemonConnection",
+        "storageKey": null,
+        "args": null,
+        "concreteType": "PokemonConnection",
+        "plural": false,
+        "selections": [
+          {
+            "kind": "LinkedField",
+            "alias": null,
+            "name": "edges",
+            "storageKey": null,
+            "args": null,
+            "concreteType": "PokemonEdge",
+            "plural": true,
+            "selections": [
+              {
+                "kind": "LinkedField",
+                "alias": null,
+                "name": "node",
+                "storageKey": null,
+                "args": null,
+                "concreteType": "Pokemon",
+                "plural": false,
+                "selections": [
+                  (v0/*: any*/),
+                  {
+                    "kind": "FragmentSpread",
+                    "name": "Show_pokemon",
+                    "args": null
+                  }
+                ]
+              }
+            ]
+          }
+        ]
+      }
+    ]
+  },
+  "operation": {
+    "kind": "Operation",
+    "name": "IndexQuery",
+    "argumentDefinitions": [],
+    "selections": [
+      {
+        "kind": "LinkedField",
+        "alias": null,
+        "name": "pokemonConnection",
+        "storageKey": null,
+        "args": null,
+        "concreteType": "PokemonConnection",
+        "plural": false,
+        "selections": [
+          {
+            "kind": "LinkedField",
+            "alias": null,
+            "name": "edges",
+            "storageKey": null,
+            "args": null,
+            "concreteType": "PokemonEdge",
+            "plural": true,
+            "selections": [
+              {
+                "kind": "LinkedField",
+                "alias": null,
+                "name": "node",
+                "storageKey": null,
+                "args": null,
+                "concreteType": "Pokemon",
+                "plural": false,
+                "selections": [
+                  (v0/*: any*/),
+                  {
+                    "kind": "ScalarField",
+                    "alias": null,
+                    "name": "iid",
+                    "args": null,
+                    "storageKey": null
+                  },
+                  {
+                    "kind": "ScalarField",
+                    "alias": null,
+                    "name": "nickname",
+                    "args": null,
+                    "storageKey": null
+                  },
+                  {
+                    "kind": "ScalarField",
+                    "alias": null,
+                    "name": "pokedexNumber",
+                    "args": null,
+                    "storageKey": null
+                  }
+                ]
+              }
+            ]
+          }
+        ]
+      }
+    ]
+  },
+  "params": {
+    "operationKind": "query",
+    "name": "IndexQuery",
+    "id": null,
+    "text": "query IndexQuery {\n  pokemonConnection {\n    edges {\n      node {\n        id\n        ...Show_pokemon\n      }\n    }\n  }\n}\n\nfragment Show_pokemon on Pokemon {\n  id\n  iid\n  nickname\n  pokedexNumber\n}\n",
+    "metadata": {}
+  }
+};
+})();
+(node as any).hash = 'd0f65678ccc4dbf9f8b745dd0213a802';
+export default node;

+ 54 - 0
app/javascript/packs/frontend/__generated__/Show_pokemon.graphql.ts

@@ -0,0 +1,54 @@
+/* tslint:disable */
+
+import { ReaderFragment } from "relay-runtime";
+declare const _Show_pokemon$ref: unique symbol;
+export type Show_pokemon$ref = typeof _Show_pokemon$ref;
+export type Show_pokemon = {
+    readonly id: string;
+    readonly iid: string;
+    readonly nickname: string | null;
+    readonly pokedexNumber: number | null;
+    readonly " $refType": Show_pokemon$ref;
+};
+
+
+
+const node: ReaderFragment = {
+  "kind": "Fragment",
+  "name": "Show_pokemon",
+  "type": "Pokemon",
+  "metadata": null,
+  "argumentDefinitions": [],
+  "selections": [
+    {
+      "kind": "ScalarField",
+      "alias": null,
+      "name": "id",
+      "args": null,
+      "storageKey": null
+    },
+    {
+      "kind": "ScalarField",
+      "alias": null,
+      "name": "iid",
+      "args": null,
+      "storageKey": null
+    },
+    {
+      "kind": "ScalarField",
+      "alias": null,
+      "name": "nickname",
+      "args": null,
+      "storageKey": null
+    },
+    {
+      "kind": "ScalarField",
+      "alias": null,
+      "name": "pokedexNumber",
+      "args": null,
+      "storageKey": null
+    }
+  ]
+};
+(node as any).hash = 'fa2ea53fc6df10adfbe4e2559578ac06';
+export default node;

+ 0 - 7
app/javascript/packs/frontend/components/pages/Pokemon.tsx

@@ -1,8 +1,6 @@
 import React, {lazy, Suspense} from 'react';
-import PropTypes from 'prop-types';
 import {Route, Switch, RouteComponentProps} from 'react-router-dom';
 
-const PokemonShow = lazy((): Promise<any> => import('./pokemon/Show'));
 const PokemonIndex = lazy((): Promise<any> => import('./pokemon/Index'));
 
 import NotFound from './NotFound';
@@ -12,7 +10,6 @@ function Pokemon({match}: RouteComponentProps<void>): React.FunctionComponentEle
     <>
       <Suspense fallback={<div>Loading...</div>}>
         <Switch>
-          <Route component={PokemonShow} exact path={`${match.path}/:id`} />
           <Route component={PokemonIndex} exact path={`${match.path}`} />
 
           <Route component={NotFound} />
@@ -22,8 +19,4 @@ function Pokemon({match}: RouteComponentProps<void>): React.FunctionComponentEle
   );
 }
 
-Pokemon.propTypes = {
-  match: PropTypes.object.isRequired,
-};
-
 export default Pokemon;

+ 42 - 35
app/javascript/packs/frontend/components/pages/pokemon/Index.tsx

@@ -1,41 +1,48 @@
 import React from 'react';
-import {RouteComponentProps} from 'react-router'; //eslint-disable-line no-unused-vars
-import {Link} from 'react-router-dom';
+import {graphql, QueryRenderer, ReadyState} from 'react-relay';
 
-interface Pokemon {
-  id: number;
-  nickname: string;
-}
-
-interface State {
-  pokemon: Pokemon[];
-}
-
-class PokemonIndex extends React.Component<RouteComponentProps<void>, State> {
-  public state = {
-    pokemon: [],
-  };
-
-  public async componentDidMount(): Promise<void> {
-    try {
-      this.setState({pokemon: [{id: 1, nickname: 'Bulbasaur'}, {id: 6, nickname: 'Charizard'}]});
-    } catch (err) {
-      // eslint-disable-next-line no-console
-      console.log(JSON.stringify(err, null, 2));
-    }
-  }
-
-  public render(): JSX.Element {
-    const pokemon: JSX.Element[] = this.state.pokemon.map(
-      (pkmn): JSX.Element => (
-        <li key={pkmn.id}>
-          <Link to={`/pokemon/${pkmn.id}`}>{pkmn.nickname}</Link>
-        </li>
-      )
-    );
+import {IndexQueryResponse} from '../../../__generated__/IndexQuery.graphql';
+import environment from '../../../graphqlEnvironment';
+import PokemonShow from './Show';
 
-    return <ul>{pokemon}</ul>;
-  }
+function PokemonIndex(): React.ReactNode {
+  return (
+    <QueryRenderer
+      environment={environment}
+      query={graphql`
+        query IndexQuery {
+          pokemonConnection {
+            edges {
+              node {
+                id
+                ...Show_pokemon
+              }
+            }
+          }
+        }
+      `}
+      render={({error, props}: ReadyState<IndexQueryResponse>): React.ReactNode => {
+        if (error) {
+          return <div>Error!</div>;
+        }
+        if (!props) {
+          return <div>Loading...</div>;
+        }
+        return (
+          <ul>
+            {props.pokemonConnection.edges.map(
+              (edge): React.ReactNode => (
+                <li key={edge.node.id}>
+                  <PokemonShow pokemon={edge.node} />
+                </li>
+              )
+            )}
+          </ul>
+        );
+      }}
+      variables={{}}
+    />
+  );
 }
 
 export default PokemonIndex;

+ 25 - 39
app/javascript/packs/frontend/components/pages/pokemon/Show.tsx

@@ -1,47 +1,33 @@
 import * as React from 'react';
-import {RouteComponentProps} from 'react-router'; //eslint-disable-line no-unused-vars
-import {Link} from 'react-router-dom';
+import {graphql, createFragmentContainer} from 'react-relay';
 
-interface Pokemon {
-  id: number;
-  nickname: string;
-}
+import {Show_pokemon as ShowPokemon} from '../../../__generated__/Show_pokemon.graphql';
 
-interface PassedRouteProps {
-  id?: string;
+interface Props {
+  pokemon: ShowPokemon;
 }
 
-interface State {
-  pokemon: Pokemon;
+function PokemonShow({pokemon}: Props): React.FunctionComponentElement<Props> {
+  const {id, iid, nickname, pokedexNumber} = pokemon;
+  return (
+    <>
+      {nickname}:{' '}
+      <ul>
+        <li>IID: {iid}</li>
+        <li>GraphQL ID: {id}</li>
+        <li>Dex #: {pokedexNumber}</li>
+      </ul>
+    </>
+  );
 }
 
-class PokemonShow extends React.Component<RouteComponentProps<PassedRouteProps>, State> {
-  public state = {
-    pokemon: {
-      id: null,
-      nickname: null,
-    },
-  };
-
-  public async componentDidMount(): Promise<void> {
-    try {
-      this.setState({pokemon: {id: 1, nickname: 'Bulbasaur'}});
-    } catch (err) {
-      // eslint-disable-next-line no-console
-      console.log(JSON.stringify(err, null, 2));
+export default createFragmentContainer(PokemonShow, {
+  pokemon: graphql`
+    fragment Show_pokemon on Pokemon {
+      id
+      iid
+      nickname
+      pokedexNumber
     }
-  }
-
-  public render(): JSX.Element {
-    return (
-      <>
-        {this.state.pokemon.id}: {this.state.pokemon.nickname}
-        <p>
-          <Link to={`${this.props.match.url}/404`}>404 page</Link>
-        </p>
-      </>
-    );
-  }
-}
-
-export default PokemonShow;
+  `,
+});