Skip to content

Commit 850cf4e

Browse files
committed
use functional components
1 parent 5ea5530 commit 850cf4e

File tree

2 files changed

+92
-80
lines changed

2 files changed

+92
-80
lines changed

src/App.js

Lines changed: 81 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,101 @@
1-
import React from "react";
1+
import React, { useState, useEffect } from "react";
22
import "./styles.css";
33
import initSqlJs from "sql.js";
44

5-
// Required to let webpack know it needs to copy the wasm file to our assets
6-
import sqlWasm from "!!file-loader?name=sql-wasm-[contenthash].wasm!sql.js/dist/sql-wasm.wasm"
5+
// Required to let webpack 4 know it needs to copy the wasm file to our assets
6+
import sqlWasm from "!!file-loader?name=sql-wasm-[contenthash].wasm!sql.js/dist/sql-wasm.wasm";
77

8-
export default class App extends React.Component {
8+
export default function App() {
9+
const [db, setDb] = useState(null);
10+
const [error, setError] = useState(null);
911

10-
constructor() {
11-
super();
12-
this.state = { db: null, err: null, results: null }
13-
}
14-
15-
componentDidMount() {
12+
useEffect(async () => {
1613
// sql.js needs to fetch its wasm file, so we cannot immediately instantiate the database
1714
// without any configuration, initSqlJs will fetch the wasm files directly from the same path as the js
1815
// see ../craco.config.js
19-
initSqlJs({
20-
locateFile: () => sqlWasm // Important
21-
})
22-
.then(SQL => this.setState({ db: new SQL.Database() }))
23-
.catch(err => this.setState({ err }));
24-
}
25-
26-
exec(sql) {
27-
let results = null, err = null;
2816
try {
29-
// The sql is executed synchronously on the UI thread.
30-
// You may want to use a web worker
31-
results = this.state.db.exec(sql); // an array of objects is returned
32-
} catch (e) {
33-
// exec throws an error when the SQL statement is invalid
34-
err = e
17+
const SQL = await initSqlJs({ locateFile: () => sqlWasm });
18+
setDb(new SQL.Database());
19+
} catch (err) {
20+
setError(err);
3521
}
36-
this.setState({ results, err })
37-
}
22+
}, []);
3823

39-
/**
40-
* Renders a single value of the array returned by db.exec(...) as a table
41-
*/
42-
renderResult({ columns, values }) {
43-
return (
44-
<table>
45-
<thead>
46-
<tr>
47-
{columns.map(columnName =>
48-
<td>{columnName}</td>
49-
)}
50-
</tr>
51-
</thead>
24+
if (error) return <pre>{error.toString()}</pre>;
25+
else if (!db) return <pre>Loading...</pre>;
26+
else return <SQLRepl db={db} />;
27+
}
5228

53-
<tbody>
54-
{values.map(row => // values is an array of arrays representing the results of the query
55-
<tr>
56-
{row.map(value =>
57-
<td>{value}</td>
58-
)}
59-
</tr>
60-
)}
61-
</tbody>
62-
</table>
63-
);
64-
}
29+
/**
30+
* A simple SQL read-eval-print-loop
31+
* @param {import("sql.js").Database} db
32+
*/
33+
function SQLRepl({ db }) {
34+
const [error, setError] = useState(null);
35+
const [results, setResults] = useState([]);
6536

66-
render() {
67-
let { db, err, results } = this.state;
68-
if (!db) return <pre>Loading...</pre>;
69-
return (
70-
<div className="App">
37+
function exec(sql) {
38+
try {
39+
// The sql is executed synchronously on the UI thread.
40+
// You may want to use a web worker here instead
41+
setResults(db.exec(sql)); // an array of objects is returned
42+
setError(null);
43+
} catch (err) {
44+
// exec throws an error when the SQL statement is invalid
45+
setError(err);
46+
setResults([]);
47+
}
48+
}
7149

72-
<h1>React SQL interpreter</h1>
50+
return (
51+
<div className="App">
52+
<h1>React SQL interpreter</h1>
7353

74-
<textarea
75-
onChange={e => this.exec(e.target.value)}
76-
placeholder="Enter some SQL. No inspiration ? Try “select sqlite_version()”"
77-
></textarea>
54+
<textarea
55+
onChange={(e) => exec(e.target.value)}
56+
placeholder="Enter some SQL. No inspiration ? Try “select sqlite_version()”"
57+
></textarea>
7858

79-
<pre className="error">{(err || "").toString()}</pre>
59+
<pre className="error">{(error || "").toString()}</pre>
8060

81-
<pre>{results
82-
? results.map(this.renderResult) // results contains one object per select statement in the query
83-
: ""
84-
}</pre>
61+
<pre>
62+
{
63+
// results contains one object per select statement in the query
64+
results.map(({ columns, values }, i) => (
65+
<ResultsTable key={i} columns={columns} values={values} />
66+
))
67+
}
68+
</pre>
69+
</div>
70+
);
71+
}
8572

86-
</div>
87-
);
88-
}
73+
/**
74+
* Renders a single value of the array returned by db.exec(...) as a table
75+
*/
76+
function ResultsTable({ columns, values }) {
77+
return (
78+
<table>
79+
<thead>
80+
<tr>
81+
{columns.map((columnName) => (
82+
<td>{columnName}</td>
83+
))}
84+
</tr>
85+
</thead>
8986

87+
<tbody>
88+
{
89+
// values is an array of arrays representing the results of the query
90+
values.map((row) => (
91+
<tr>
92+
{row.map((value) => (
93+
<td>{value}</td>
94+
))}
95+
</tr>
96+
))
97+
}
98+
</tbody>
99+
</table>
100+
);
90101
}

src/styles.css

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,34 @@
33
font-size: 1.5em;
44
}
55

6-
textarea{
6+
textarea {
77
font-size: 1.1em;
88
width: 70%;
99
display: block;
10-
margin:auto;
10+
margin: auto;
1111
}
1212

13-
table{
14-
border: 1px solid #1C6EA4;
15-
background-color: #EEEEEE;
13+
table {
14+
border: 1px solid #1c6ea4;
15+
background-color: #eeeeee;
1616
width: 40%;
1717
margin: 1.5em auto;
1818
text-align: left;
1919
border-collapse: collapse;
2020
text-align: right;
2121
}
2222

23-
thead{
23+
thead {
2424
font-weight: bold;
2525
text-align: center;
2626
border: 2px solid #999;
2727
}
2828

29-
th, td{
29+
th,
30+
td {
3031
border: 1px solid #aaa;
3132
}
3233

33-
.error{
34-
color:#922;
35-
}
34+
.error {
35+
color: #922;
36+
}

0 commit comments

Comments
 (0)