Use data-backed components to rapidly transform your workflow.

Data backed components code example.

It may not look like much, but this react component is fully backed by highly performant, auto-scaling cloud infrastructure that is connected to a running database and is executable anywhere javascript can run.

import nokori from 'nokori'

async function handleSubmit(formData: FormData){
 const {data, error} = await nokori.query.execute({
      // Global special purpose cloud function id
  		queryId: 'nk.q.-ddqHfqeZNihbChcAbf', 
  			context: {
    			name: formDate.get('name')
  			} 
		}
  )
}

export default function Page() {
  return (
    <form action={handleSubmit}>
      <input type="text" name="name" />
      <button type="submit">Submit</button>
    </form>
  )
}

Upon form submission, the data from the form is inserted into a running database you've preconfigured in your nokori dashboard. No backend API to build with legacy frameworks like Express.js, and no infrastructure to manage.

This is why we've built Special Purpose Cloud Functions™ as a part of Hubs. The legacy approach of using technologies like Express.js to spend hours building a backend API simply to fetch, update, and/or delete data from a running database is long, arduous, and completely unnecessary.

The "modern" approach of using Edge Functions to replace the traditional backend API is wrought with it's own significant time overhead and unoptimized developer experience.

Legacy Edge Functions Have Underdelivered

When AWS Lambda first came on the scene, it promised speed, agility, and a significant reduction in developer headaches when launching new data-rich applications in the cloud.

While competitors have since come and gone, the reality is that legacy Edge Functions largely resulted in the same (or more) code, clunky local development experiences, and non-intuitive, slow, painful deployment processes.

We've built Special Purpose Cloud Functions™(SPCF) to address these challenges head on, ushering in the next generation of cloud-native functions. We believe what we've come up with is truly special.

SPCFs are an extremely low-code approach to building cloud-native functions that target the world's most common backend usecases: fetching and updating data.

Whether it's in a MySQL table, PostGres, or any HTTP REST API, our SPCFs empower engineers to rapidly configure those targeted data connections, instantly deploy those functions, and get back to developing the actual application they want to build.

A Simple Example

You can find the full example project here:

Imagine you run an online "Cosmic Soda Shop" where customers place orders for your delightful array of specialty, space-themed sodas.

Internally, you likely have a database that tracks when these orders are placed, but you need a User Interface that allows your team to easily view orders in real-time to ensure orders are fulfilled right away.

In five minutes or less, we're going to build our cloud function to query the orders table, and then launch a data-backed component to automagically fill our table with orders.

Test Data

If you're following along, you can execute this query in a test MySQL database to create the same test data we are using here.

CREATE DATABASE  IF NOT EXISTS `nokori_demo`;
USE `nokori_demo`;

DROP TABLE IF EXISTS `orders`;

CREATE TABLE `orders` (
  `orderId` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL,
  `createdAt` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `productId` varchar(45) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `productName` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `quantity` varchar(45) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `customerId` varchar(45) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`orderId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO `orders` VALUES 
('3589488','2023-02-03 21:57:45','prd.id.83194822','KosmicKrush','6','897788'),
('3589489','2023-02-03 21:58:10','prd.id.91192877','MoonMist','3','637786'),
('3589490','2023-02-03 21:59:06','prd.id.19473378','CosmiGulp','5','794576'),
('3589491','2023-02-03 21:59:39','prd.id.81117378','Stardrizzle','12','384164'),
('3589492','2023-03-08 00:50:58','prd.id.98382233','AstroFizz','24','964587');

Now that we’ve got some demo data, let’s create a SPCF to fetch the data our app will need.

Setting up the query and cloud function

As we've mentioned, we're going to completely skip building a backend API or writing boilerplate MySQL code that still has to be deployed somewhere.

Within the nokori UI, we are simply going to compose our SQL query, grab the query id generated by the platform, and use that to instantly consume data in our app.

Example showing a SQL query being configured in the nokori Hubs UI

After creating our Cloud Function in the UI, the app immediately gives us our Query ID(visible in the top right corner) that we’ll use to access our database. The query id in this case is: nk.q.6WQiTJ2PLJnBiYQVLQt

Tip: Your query id will be different, so don’t try to use this one or it won’t work and there will be many, many tears 😭😭😭

Like what we find in our React Basic Example from our Examples Repo, we will implement a basic react component that pulls data from our database.

Creating our React App

You can whip together a React shell app quickly with this command:

npx create-react-app nokori-cosmic-soda-shop
cd nokori-cosmic-soda-shop
npm run start

You should have a working react app now, but only one problem, there’s no data!

Let's install the nokori SDK:

npm i @nokori/js-sdk

Once installed, let’s open App.js in our React app and make some changes.

First we’re going to import the nokori SDK, as well as two popular React hooks, useState and useEffect.

import React, { useState, useEffect } from "react";
import Nokori from '@nokori/js-sdk';
import './App.css';
const nokori = new Nokori(process.env.REACT_APP_NOKORI_API_KEY);

(Aside: in your react app you’ll need to put your nokori API key in a .env file, or, you can replace the process.env.REACT_APP_NOKORI_API_KEY portion of this code with the API key.)

Our React shell comes with a basic component App function by default that looks like this:

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

We’re going to update it in two parts: Part 1 — using useState and useEffect to get our orders from our MySQL database. Part 2 — build a simple table that iterates over the data to build our table on load.

Part 1 — Get order data from MySQL

Here’s all of the code required to connect to and query your database to get our recent orders:

// function App() {
const [loadingData, setLoadingData] = useState(true);
const [data, setData] = useState([]);

useEffect(() => {
  async function getData() {
    const {
      data: results, 
      error
    } = await lola.query.execute({
        queryId: 'lola.q.6WQiTJ2PLJnBiYQVLQt'
      })

    if (error) {
      console.error(error);
    }

    if(results && !error) {
      setData(results);
      setLoadingData(false);
    }
  }
  
  if (loadingData) {
    getData();
  }
});

//return (

Just after the opening App() function declaration, we use useEffect to get data from MySQL by calling our lola.query.execute function with the Query Id that was created when you created your query in lolaDB.

We use some ES6+ syntactic sugar to destructure the results and assign data to a ‘results’ const. Because useEffect is reactive, when lolaDB successfully gets data from MySQL, our table (in the next part) will automatically populate with data.

Part 2 — Populate our table with the results

We’ll update the return() portion of our page with the following:

return (
    <div className="App">
      <h1>React lolaDB Example</h1>
      <p>
        In this fictitious example, we are fetching customer orders from our database of soda orders at
        our Cosmic Soda Shop.
      </p>
      <h2>Orders list</h2>
      {/* here you check if the state is loading otherwise if you wioll not call that you will get a blank page because the data is an empty array at the moment of mounting */}
      {
        loadingData && !data ? (
          <p>Loading Please wait...</p>
        ) : (
        <table>
          <thead>
          <tr>
            <th>Order ID</th>
            <th>Product Name</th>
            <th>Quantity</th>
            <th>Customer Id</th>
          </tr>
          </thead>
          <tbody>
          { 
          !loadingData && data.map((order) => {
            return <tr key={order.orderId}>
              <td>{order.orderId}</td>
              <td>{order.productName}</td>
              <td>{order.quantity}</td>
              <td>{order.customerId}</td>
            </tr>
          })
          }
          </tbody>
        </table>
      )}
    </div>
  );

Using the loadingData state variable we wait until data has arrived, and then we iterate over the results and build the table.

The magic code here is the nokori query:

const { data: results, error } = await nokori.query.execute({
  queryId: '{{YOUR_QUERY_ID}}'
})

Just two lines of code, and we query your database in real-time. No scaffolding. No hours of building an API just so you can get data in your frontend app.

Bringing it all together, this is our full page component:

import React, { useState, useEffect } from "react";
import Nokori from '@nokori/js-sdk';
import './App.css';
const nokori = new Nokori(process.env.REACT_APP_NOKORI_API_KEY);

function App() {
  const [loadingData, setLoadingData] = useState(true);
  const [data, setData] = useState([]);

  useEffect(() => {
    async function getData() {
      const {
        data: results, 
        error
      } = await nokori.query.execute({
          queryId: 'nk.q.6WQiTJ2PLJnBiYQVLQt'
        })

      if (error) {
        console.error(error);
      }

      if(results && !error) {
        setData(results);
        setLoadingData(false);
      }
    }
    
    if (loadingData) {
      getData();
    }
  });

  return (
    <div className="App">
      <h1>React nokori Example</h1>
      <p>
        In this fictitious example, we are fetching customer orders from our database of soda orders at
        our soda shop.
      </p>
      <h2>Orders list</h2>
      {/* here you check if the state is loading otherwise if you wioll not call that you will get a blank page because the data is an empty array at the moment of mounting */}
      {
        loadingData && !data ? (
          <p>Loading Please wait...</p>
        ) : (
        <table>
          <thead>
          <tr>
            <th>Order ID</th>
            <th>Product Name</th>
            <th>Quantity</th>
            <th>Customer Id</th>
          </tr>
          </thead>
          <tbody>
          { 
          !loadingData && data.map((order) => {
            return <tr key={order.orderId}>
              <td>{order.orderId}</td>
              <td>{order.productName}</td>
              <td>{order.quantity}</td>
              <td>{order.customerId}</td>
            </tr>
          })
          }
          </tbody>
        </table>
      )}
    </div>
  );
}

export default App;

Let’s test it out!

Run npm run start in the console, and then open up your browser to the localhost link the console gives you.

Voila! Houston, we have data from a real live database, all without building an API.

The result of using nokori Special Purpose Functions. Show's a react table rendered with real data.

Wrapping Up

As you've seen, using our new Special Purpose Cloud Functions™ we just built a data-backed component that allows developers to tightly couple their data access logic with the component consuming it without sacrificing on maintainability or reusability of the data access logic.

SPCFs are always on and never have cold-starts. Furthermore, as you've seen, our intuitive UI makes configuring access to your backend data source as easy as testing an endpoint with great tools like Postman.

While we used MySQL in this example, it could have easily been the Shopify API, ElasticSearch, MongoDB, etc.

Feel free to reach out to hello[at]nokori.com with questions and feedback - we love talking shop with other passionate developers.

Thanks! ✌️

Join the newsletter.

Receive updates when we ship new features, as well as tips and guides for getting the most out of nokori.

Timely articles
We only publish high quality content when we have something to useful to share. No fluff, no spam.