Skip to main content

React

EmbraceSQL generates support for React using hooks. The hooks:

  • Connect to any HTTP/S EmbraceSQL server endpoint
  • Create, Read, Update, Delete, and Refresh data (CRUD-R)

Requirements

You are going to need:

  • NodeJs >= 18
  • PostgreSQL >= 14

These examples assume you are running locally with your shell able to connect to your PostgreSQL with:

psql

Create a new database dvdrental on your local PostgeSQL server.

curl "https://embracesql.github.io/dvdrental.sql" | psql

Steps

In this example you will end up with read-write data access from a hot loading Vite built application without:

  • Writing a line of SQL
  • Making a POJO
  • Learning a new 'schema language' like in Prisma
  • Learning a new 'query language' like GraphQL
  • Calling the database manually

Generate an Express Server

Go into a nice blank directory. This is the 'server side'.

npm install @embracesql/vite
npm pkg set type=module
mkdir -p ./src
npx embracesqlcli generate express --database postgres://postgres:postgres@localhost/dvdrental > ./src/dvdrental.ts

Yeah -- that's it, hard to believe I know...

Code up an Express Server

Create two files as shown.

tsconfig.json
{
"extends": "@embracesql/shared/tsconfig/react.tsconfig.json"
}
./src/server/main.ts
import { EmbraceSQLExpressApp } from "./dvdrental";
import { EmbraceViteApp } from "@embracesql/vite";
import express from "express";

const app = express();

export const PORT = Number.parseInt(process.env["PORT"] ?? "4000");

// hook EmbraceSQL middleware first to connect to the database
const embracesql = await EmbraceSQLExpressApp(
"postgres://postgres:postgres@localhost/dvdrental",
);
// mounting the database middleware
app.use("/embracesql", embracesql);
// and then hook in vite middleware to build and run your React
const vite = await EmbraceViteApp();
// server react at the root
app.use("/", vite);

app.listen(PORT, () => console.log(`Server is listening on port ${PORT}...`));

Run Your Server

Make sure the server starts -- this will even hot reload the server -- and web page we're about to build.

npx tsx watch ./src/server/main.ts

At this point, if you are getting data -- it's time to make a react app!

Generate a React Client

Generate the client side, react hook code:

mkdir -p src/client
npx embracesqlcli generate react --database postgres://postgres:postgres@localhost/dvdrental > ./src/client/dvdrental-react.ts

Code up a React App

Here is a super minimal React application to get you a single Actor from the database, and allow saving to the database without you writing a line of SQL, or additional schema, or even a server.

Gonna need an html page entry point.

index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Checklist</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/client/main.tsx"></script>
</body>
</html>

And attach a react component to #root.

./src/client/main.tsx
import {
EmbraceSQLClient,
EmbraceSQLProvider,
Public,
} from "./dvdrental-react";
import "./main.css";
import * as ReactDOM from "react-dom/client";

// connect to where we mounted EmbraceSQL in our server
const client = new EmbraceSQLClient({
url: `${window.location.href}embracesql`,
});

const App = () => {
// this is hooking to an AutoCRUD method to read an actor
const {
loading,
row: actor,
error,
} = Public.Tables.Actor.useActorPkey({ actorId: 100 });
// 🪄 - automatic onChange saving though the hook, with debounce to not smoke your DB!
// notice there is no <form> to post back or additional hooks
if (loading) {
return (
<div>
<p>Loading...</p>
</div>
);
}
if (error) {
return (
<div>
<p>{`{error}`}</p>
</div>
);
}
if (actor) {
return (
<div className="card">
<input value={actor.firstName} onChange={actor.changeFirstName} />
<input value={actor.lastName} onChange={actor.changeLastName} />
</div>
);
}
};

// Supported in React 18+
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
<EmbraceSQLProvider client={client}>
<App />
</EmbraceSQLProvider>,
);

And just a tiny bit of CSS:

./src/client/main.css
#root {

max-width: 100vw;
margin: 0 auto;
padding: 2rem;
text-align: center;
}

body {
font-family: system-ui;
margin: 0;
display: flex;
place-items: center;
min-width: 100vw;
min-height: 100vh;
}

.card {
padding: 2em;
display: flex;
flex-direction: column;
row-gap: 1rem;
}

OK - the Express server should now be serving both EmbraceSQL and a fine React app connected to it. Check it out.