Build a pokemon collectibles app in React.js in minutes 👨‍💻
Published: 2023-12-13 10:03:22


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5yoh869nrvobzt9gdajf.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lsb20oqjultviufz6n6v.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o4nfwoosen5fzi682h6y.png)


## What we'll be building?

We'll be building a Pokemon collectibles app. You can have users signup and a database of Pokemon to choose from. After a user collects a Pokemon, it's his. It's first come first serve.

For this, we'll need

- Authentication for users
- DB to store, users and Pokemon
- Pokemon data
- A mapping or a foreign key to track which Pokemon belongs to who
- Realtime notification system for tracking Pokemon collection
- Front-end in React.js

Luckily we have [Rocketgraph](https://rocketgraph.io) which provides this functionality right out of the box. Let's leverage that to build this much faster.

> 💡To read this article you need to have a basic understanding of React.js and PostgreSQL

## [Rocketgraph](https://rocketgraph.io) : A complete backend that beats Firebase and is open-source

A little background. Rocketgraph provides a complete backend. It comes with a Postgres DB, Hasura console to manage your Postgres and add GraphQL layer to your data, Authentication and Serverless functions.

So to sum it up we provide auth for your web apps, GraphQL for realtime things like messages/notifications/comments etc and Serverless functions for anything you want to offload. Deploy your serverless functions by running `rgraph deploy <project name>` in your repo.

## So what the hack is GraphQL?

GraphQL is a language specification by Meta to achieve realtime queries on your data by asking for exactly what you need. This is different from traditional API approach where the query is coded into the backend and front-end has very little control over what/how to ask for data.

Think of it like a JSON query. You ask for what data you want inn a json-like query and it will return exactly those fields.

In this article we'll leverage the power of GraphQL, React Apollo and Hasura to build a real-time system for rating and commenting on movies. We can use this same system to book movie tickets too.

## TLDR Version

If you just want to see the code. Here is the [code base for this article](https://github.com/RocketsGraphQL/rgraph/tree/master/example-setups/movie-voting). Here you can see [more examples](https://github.com/RocketsGraphQL/rgraph/tree/master/example-setups). This is the [open-source software](https://github.com/RocketsGraphQL/hasura-batteries) behind Rocketgraph

Keep reading

![keep reading gif](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yma0zrp48i934bppq3pc.jpeg)

## Before you start

Signup on [Rocketgraph](https://rocketgraph.io/signup) and create a project. This will also spin up an AWS RDS Postgres DB that we'll use to store our pokemon data. Once it's complete,

## Cool, let's start from the basics
Create a react project and develop the front-end. Forget about the backend, we'll add it later.


```bash
mkdir pokemon-app && cd pokemon-app
```

Next scaffold a basic react application.

```bash
npx create-react-app ./
```

Install [react router](https://www.npmjs.com/package/react-router-dom) to be able to navigate between pages. Install react-apollo and graphql for real-time stuff as mentioned above.

```bash
yarn add react-router-dom
yarn add @apollo/client graphql
```

Next add some Rocketgraph libraries

```
yarn add @rocketgraphql/react-apollo
yarn add @rocketgraphql/rocketgraph-js-sdk
```

Delete the redundant files such as logo from the project and update the index.js file to as follows:

```js
// src/index.js
import React from "react";
import ReactDOM from "react-dom";
import { Login } from "./components/login";
import { Signup } from "./components/signup";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import App from "./App";
import { RApolloProvider } from "@rocketgraphql/react-apollo";
import { auth } from "./utils/rockets";

ReactDOM.render(
  <React.StrictMode>
      <RApolloProvider auth={auth} gqlEndpoint="https://hasura-vlklxvo.rocketgraph.app/v1/graphql">
        <Router>
          <Routes>
            <Route path="/login" element={<Login />}/>
            <Route path="/signup" element={<Signup />}/>
            <Route path="/" element={<App />} />
          </Routes>
        </Router>
      </RApolloProvider>
  </React.StrictMode>,
  document.getElementById("root")
);
```

And replace your `gqlEndpoint` value with that on your Hasura console here:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ftu33ce9oc7m4ar2fkcn.png)

App.js

```js
import './App.css';

import { gql, useMutation, useSubscription } from "@apollo/client";


const GET_TODOS = gql`
  subscription {
    pokemon(limit: 100, order_by: {id: asc}) {
      id
      identifier
      user_id
    }
  }
`;

const COLLECT = gql`
  mutation MyMutation($name: String!) {
    update_pokemon(where: {identifier: {_eq: $name}}, _set: {identifier: $name}) {
      affected_rows
    }
  }
`

const PokemonComponent = (poke, func) => {
  return (
    <>
      <li key={poke.id}>{poke.identifier}
        {
          poke.user_id ?
          " collected"
          : <button onClick={() => {console.log(poke); func(poke.identifier)}}>collect</button>
        }
      </li>
    </>
  )
}
function App() {
  const { data, loading } = useSubscription(GET_TODOS);
  console.log("data, loading", data, loading);
  const [collectPoke, { poke_mutate, poke_loading }] = useMutation(COLLECT);
  const collectPokemon = (poke_name) => {
    collectPoke({ variables: { name: poke_name} });
}
  return (
    <div className="App">
        {!data || !data.pokemon || !data.pokemon.length ? (
          "no data"
        ) : (
          <ul id="todosList">
            {data.pokemon.map((poke) => {
              return PokemonComponent(poke, collectPokemon);
            })}
          </ul>
        )}
    </div>
  );
}

export default App;
```

components/signup:

```js
import React, { useState } from "react";
import { useNavigate } from 'react-router-dom';
import { auth } from "../utils/rockets";

export function Signup(props) {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const navigate = useNavigate();

  async function handleSubmit(e) {
    e.preventDefault();

    // login
    try {
        await auth.register({email, password});
        navigate("/")
      } catch (error) {
        alert("error signing up");
        console.error(error);
        return;
    }

  }

  return (
    <div>
      <h1>Signup</h1>
      <form onSubmit={handleSubmit}>
        <input
          id="inputUserEmail"
          type="email"
          placeholder="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
        />
        <input
          id="inputUserPassword"
          type="password"
          placeholder="password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
        />
        <button id="signupButton">Signup</button>
      </form>
    </div>
  );
}
```

## Aaaand, we are done!!

You can host your app on Vercel, use tailwind to make it look more professional.