~repos /edge-city
git clone https://pyrossh.dev/repos/edge-city.git
edge-city is a next level meta-framework for react that runs only on edge runtimes
90cd3aad
—
Peter John 2 years ago
use react-hook-form
- bun.lockb +0 -0
- package.json +1 -0
- pages/todos/page.jsx +10 -8
- parotta/runtime.js +17 -13
bun.lockb
CHANGED
|
Binary file
|
package.json
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"react-dom": "18.2.0",
|
|
21
21
|
"react-error-boundary": "4.0.4",
|
|
22
22
|
"react-helmet-async": "1.3.0",
|
|
23
|
+
"react-hook-form": "7.43.9",
|
|
23
24
|
"sql-highlight": "^4.3.2"
|
|
24
25
|
},
|
|
25
26
|
"devDependencies": {
|
pages/todos/page.jsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import React, { Suspense
|
|
1
|
+
import React, { Suspense } from 'react';
|
|
2
2
|
import { Helmet } from 'react-helmet-async';
|
|
3
3
|
import { useQuery, useMutation } from "parotta/runtime";
|
|
4
|
+
import { useForm } from 'react-hook-form';
|
|
4
5
|
import Todo from "@/components/Todo/Todo";
|
|
5
6
|
import { TextField, Label, Input } from 'react-aria-components';
|
|
6
7
|
import { Button } from 'react-aria-components';
|
|
@@ -9,8 +10,8 @@ import Layout from '@/components/Layout/Layout';
|
|
|
9
10
|
import "./page.css";
|
|
10
11
|
|
|
11
12
|
const TodoList = () => {
|
|
12
|
-
const { data, refetch } = useQuery(
|
|
13
|
+
const { data, refetch } = useQuery("todos", () => getTodos());
|
|
13
|
-
const { mutate, isMutating } = useMutation(async () => {
|
|
14
|
+
const { mutate, isMutating } = useMutation(async ({ text }) => {
|
|
14
15
|
await createTodo({
|
|
15
16
|
text,
|
|
16
17
|
completed: false,
|
|
@@ -18,7 +19,7 @@ const TodoList = () => {
|
|
|
18
19
|
})
|
|
19
20
|
await refetch();
|
|
20
21
|
});
|
|
21
|
-
const
|
|
22
|
+
const { register, handleSubmit, formState: { errors } } = useForm();
|
|
22
23
|
return (
|
|
23
24
|
<div>
|
|
24
25
|
<ul>
|
|
@@ -26,16 +27,17 @@ const TodoList = () => {
|
|
|
26
27
|
<Todo key={item.id} todo={item} />
|
|
27
28
|
))}
|
|
28
29
|
</ul>
|
|
29
|
-
<
|
|
30
|
+
<form onSubmit={handleSubmit(mutate)}>
|
|
30
31
|
<TextField isRequired isReadOnly={isMutating}>
|
|
31
32
|
<Label>Text (required)</Label>
|
|
32
|
-
<Input
|
|
33
|
+
<Input {...register('text', { required: true })} />
|
|
34
|
+
{errors.text && <p>Please enter some text</p>}
|
|
33
35
|
</TextField>
|
|
34
|
-
<Button
|
|
36
|
+
<Button type="submit" isDisabled={isMutating}>Add Todo</Button>
|
|
35
37
|
{isMutating && <div>
|
|
36
38
|
<p>Creating...</p>
|
|
37
39
|
</div>}
|
|
38
|
-
</
|
|
40
|
+
</form>
|
|
39
41
|
</div>
|
|
40
42
|
)
|
|
41
43
|
}
|
parotta/runtime.js
CHANGED
|
@@ -19,14 +19,18 @@ export const rpc = (serviceName) => async (params = {}) => {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export const RpcContext = createContext(undefined);
|
|
22
|
+
|
|
22
23
|
// global way to refresh maybe without being tied to a hook like refetch
|
|
23
|
-
|
|
24
|
+
export const useInvalidate = () => {
|
|
25
|
+
const ctx = useContext(RpcContext);
|
|
26
|
+
return (regex) => {
|
|
24
|
-
|
|
27
|
+
Object.keys(ctx)
|
|
25
|
-
|
|
28
|
+
.filter((k) => regex.test(k))
|
|
26
|
-
|
|
29
|
+
.forEach((k) => {
|
|
27
|
-
// fetchData(k).then((v) => set(k, v));
|
|
28
|
-
// });
|
|
29
|
-
|
|
30
|
+
delete ctx[k];
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
30
34
|
|
|
31
35
|
export const useRpcCache = (k) => {
|
|
32
36
|
const ctx = useContext(RpcContext);
|
|
@@ -37,7 +41,7 @@ export const useRpcCache = (k) => {
|
|
|
37
41
|
rerender((c) => !c);
|
|
38
42
|
}
|
|
39
43
|
const invalidate = () => {
|
|
40
|
-
ctx[k]
|
|
44
|
+
delete ctx[k];
|
|
41
45
|
rerender((c) => !c);
|
|
42
46
|
}
|
|
43
47
|
return {
|
|
@@ -49,19 +53,19 @@ export const useRpcCache = (k) => {
|
|
|
49
53
|
|
|
50
54
|
/**
|
|
51
55
|
*
|
|
52
|
-
* @param {*} fn
|
|
56
|
+
* @param {*} fn
|
|
53
57
|
* @param {*} params
|
|
54
58
|
* @returns
|
|
55
59
|
*/
|
|
56
|
-
export const useQuery = (
|
|
60
|
+
export const useQuery = (key, fn) => {
|
|
57
61
|
const [isRefetching, setIsRefetching] = useState(false);
|
|
58
62
|
const [err, setErr] = useState(null);
|
|
59
|
-
const cache = useRpcCache(
|
|
63
|
+
const cache = useRpcCache(key);
|
|
60
64
|
const refetch = useCallback(async () => {
|
|
61
65
|
try {
|
|
62
66
|
setIsRefetching(true);
|
|
63
67
|
setErr(null);
|
|
64
|
-
cache.set(await fn(
|
|
68
|
+
cache.set(await fn());
|
|
65
69
|
} catch (err) {
|
|
66
70
|
setErr(err);
|
|
67
71
|
throw err;
|
|
@@ -78,7 +82,7 @@ export const useQuery = (fn, params) => {
|
|
|
78
82
|
}
|
|
79
83
|
return { data: value, isRefetching, err, refetch };
|
|
80
84
|
}
|
|
81
|
-
cache.set(fn(
|
|
85
|
+
cache.set(fn().then((v) => cache.set(v)));
|
|
82
86
|
throw cache.get();
|
|
83
87
|
}
|
|
84
88
|
|