How to create a real-time blockchain data app in React

We will build a React application that fetches data from Bitquery using a WebSocket connection to a GraphQL server and displays the retrieved data in a list.

Let’s create a react an empty application using

npx create-react-app

This will create a template app which we will modify. The core of our logic will be stored in a separate file, let’s say subscriptioncomponent.js . We will now build the component.

subscriptioncomponent.js

  1. Import React, useEffect and useState from ‘react’, and axios for HTTP requests.
import React, { useEffect, useState } from 'react';
import axios from 'axios';
  1. Declare a functional component named ‘MyComponent’, and initialize its state with an empty array using useState. This array will hold the transfer data fetched from the server.
export function MyComponent() {
  const [data, setData] = useState([]);
  1. Use the useEffect hook to establish a WebSocket connection to the GraphQL server when the component mounts. The effect will only run once since the dependencies array is empty. Inside the useEffect function, declare a URL for the GraphQL server, and a JSON message to be sent to the server to initiate a subscription.

The query mentioned here retrieves transfer data. To get the API key, go here Bitquery

useEffect(() => {
    const url = 'wss://streaming.bitquery.io/graphql';
    const message = JSON.stringify({
      "type": "start",
      "id": "1",
      "payload": {
        "query": "subscription {\n  EVM {\n    Transfers {\n      Transfer {\n        Amount\n        __typename\n        Currency {\n          __typename\n          Symbol\n        }\n      }\n    }\n  }\n}",
        "variables": {}
      },
      "headers": {
        "Authorization": "Bearer your_access_token_here"
      }
    });
  1. Create a WebSocket object, and define a ‘connect’ function to open a new WebSocket connection and send the subscription message to the server. Set up ‘onmessage’ event handler to update the state with the transfer data received from the server if the response type is ‘data’.
    let ws = new WebSocket(url, 'graphql-ws');

    const connect = () => {
      ws = new WebSocket(url, 'graphql-ws');

      ws.onopen = () => {
        ws.send(message);
      };

      ws.onmessage = (event) => {
        const response = JSON.parse(event.data);

        if (response.type === 'data') {
          setData(response.payload.data.EVM.Transfers.map(t => t.Transfer));
        }
      };
  1. Define an ‘onclose’ event handler to handle disconnection, and set a timeout to retry connection in 5 seconds after disconnection.
      ws.onclose = () => {
        console.log("WebSocket disconnected. Retrying in 5 seconds...");
        setTimeout(connect, 5000);
      };
    };

    connect();
  1. Return a cleanup function from useEffect that closes the WebSocket connection and logs a message to the console. Pass an empty array as a dependency for the cleanup function to run only when the component unmounts.
    return () => {
      ws.close();
      console.log("WebSocket disconnected.");
    };
  }, []);
  1. Render the component by returning a div element containing a header and an unordered list. Map over the transfer data in the state and display it in a list item.
  return (
    <div>
      <h1>Transfer Data:</h1>
      <ul>
        {data.map((item, index) => (
          <li key={index}>
            {item.Amount} {item.Currency.Symbol}
          </li>
        ))}
      </ul>
    </div>
  );
}

App.js

The app.js will render the component on localhost.

import './App.css';
import {MyComponent} from './subscriptioncomponent.js'
function App() {
  return (
    <div className="App">
     
      <MyComponent/>
    </div>
  );
}

export default App;

Run the app and open localhost:8000 . This is how it will look at the end, go on and improve the UI as you like
subscription_react

Full GitHub repo is available here GitHub - bitquery/React-Subscriptions-Sample

1 Like