-
Notifications
You must be signed in to change notification settings - Fork 33
/
App.js
102 lines (90 loc) · 2.76 KB
/
App.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import React, { useState, useEffect } from "react";
import "./styles.css";
import initSqlJs from "sql.js";
// Required to let webpack 4 know it needs to copy the wasm file to our assets
import sqlWasm from "!!file-loader?name=sql-wasm-[contenthash].wasm!sql.js/dist/sql-wasm.wasm";
export default function App() {
const [db, setDb] = useState(null);
const [error, setError] = useState(null);
useEffect(async () => {
// sql.js needs to fetch its wasm file, so we cannot immediately instantiate the database
// without any configuration, initSqlJs will fetch the wasm files directly from the same path as the js
// see ../craco.config.js
try {
const SQL = await initSqlJs({ locateFile: () => sqlWasm });
setDb(new SQL.Database());
} catch (err) {
setError(err);
}
}, []);
if (error) return <pre>{error.toString()}</pre>;
else if (!db) return <pre>Loading...</pre>;
else return <SQLRepl db={db} />;
}
/**
* A simple SQL read-eval-print-loop
* @param {{db: import("sql.js").Database}} props
*/
function SQLRepl({ db }) {
const [error, setError] = useState(null);
const [results, setResults] = useState([]);
function exec(sql) {
try {
// The sql is executed synchronously on the UI thread.
// You may want to use a web worker here instead
setResults(db.exec(sql)); // an array of objects is returned
setError(null);
} catch (err) {
// exec throws an error when the SQL statement is invalid
setError(err);
setResults([]);
}
}
return (
<div className="App">
<h1>React SQL interpreter</h1>
<textarea
onChange={(e) => exec(e.target.value)}
placeholder="Enter some SQL. No inspiration ? Try “select sqlite_version()”"
></textarea>
<pre className="error">{(error || "").toString()}</pre>
<pre>
{
// results contains one object per select statement in the query
results.map(({ columns, values }, i) => (
<ResultsTable key={i} columns={columns} values={values} />
))
}
</pre>
</div>
);
}
/**
* Renders a single value of the array returned by db.exec(...) as a table
* @param {import("sql.js").QueryExecResult} props
*/
function ResultsTable({ columns, values }) {
return (
<table>
<thead>
<tr>
{columns.map((columnName, i) => (
<td key={i}>{columnName}</td>
))}
</tr>
</thead>
<tbody>
{
// values is an array of arrays representing the results of the query
values.map((row, i) => (
<tr key={i}>
{row.map((value, i) => (
<td key={i}>{value}</td>
))}
</tr>
))
}
</tbody>
</table>
);
}