DEV Community

Cover image for Build a pokemon collectibles app in React.js in minutes πŸ‘¨β€πŸ’»
Kaushik Varanasi
Kaushik Varanasi

Posted on

Build a pokemon collectibles app in React.js in minutes πŸ‘¨β€πŸ’»

Image description

Image description

Image description

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 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 : 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. Here you can see more examples. This is the open-source software behind Rocketgraph

Keep reading

keep reading gif

Before you start

Signup on Rocketgraph 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.

mkdir pokemon-app && cd pokemon-app
Enter fullscreen mode Exit fullscreen mode

Next scaffold a basic react application.

npx create-react-app ./
Enter fullscreen mode Exit fullscreen mode

Install react router to be able to navigate between pages. Install react-apollo and graphql for real-time stuff as mentioned above.

yarn add react-router-dom
yarn add @apollo/client graphql
Enter fullscreen mode Exit fullscreen mode

Next add some Rocketgraph libraries

yarn add @rocketgraphql/react-apollo
yarn add @rocketgraphql/rocketgraph-js-sdk
Enter fullscreen mode Exit fullscreen mode

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

// 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")
);
Enter fullscreen mode Exit fullscreen mode

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

Image description

App.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;
Enter fullscreen mode Exit fullscreen mode

components/signup:

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>
  );
}
Enter fullscreen mode Exit fullscreen mode

Aaaand, we are done!!

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

Top comments (5)

Collapse
 
nombrekeff profile image
Keff

Hahahaha 2 years is also minutes 😝

Collapse
 
kaushik94 profile image
Kaushik Varanasi

It looks long because of the code and screenshots. But when you get down to it, it takes about half an hour.

Collapse
 
nombrekeff profile image
Keff

I know I know, I was just kidding. What I meant was that anything that costs more than a minute can be done in minutes hehehe 😝

Thread Thread
 
kaushik94 profile image
Kaushik Varanasi

haha, you have a fair point though. People like concise numbers like "15 minutes". Guess I have to change the tagline haha.

Thread Thread
 
nombrekeff profile image
Keff

Hahahaha no need, it made me take a read