edge-city
git clone https://git.pyrossh.dev/edge-city
edge-city is a next level meta-framework for react that runs only on edge runtimes
example/src/pages/todos/Todo.jsx
| ce83445 | 1 | import { useState } from "react"; |
| ce83445 | 2 | import { useForm } from "react-hook-form"; |
| ce83445 | 3 | import { TextField, Input } from "react-aria-components"; |
| c7f7584 | 4 | import { cache, useMutation } from "edge-city/data"; |
| ce83445 | 5 | import { updateTodo, deleteTodo } from "@/services/todos.service"; |
| ce83445 | 6 | import "./Todo.css"; |
| ce83445 | 7 | |
| ce83445 | 8 | const Todo = ({ item }) => { |
| ce83445 | 9 | const [editing, setEditing] = useState(false); |
| ce83445 | 10 | const { |
| ce83445 | 11 | register, |
| ce83445 | 12 | handleSubmit, |
| ce83445 | 13 | reset, |
| ce83445 | 14 | } = useForm(); |
| ce83445 | 15 | const updateMutation = useMutation(async ({ text }) => { |
| ce83445 | 16 | await updateTodo({ id: item.id, text, completed: item.completed }); |
| f07784d | 17 | await cache.invalidate("todos", false); |
| ce83445 | 18 | setEditing(false); |
| ce83445 | 19 | }); |
| ce83445 | 20 | const deleteMutation = useMutation(async (id) => { |
| ce83445 | 21 | await deleteTodo(id); |
| f07784d | 22 | await cache.invalidate("todos", false); |
| ce83445 | 23 | }); |
| ce83445 | 24 | return ( |
| f07784d | 25 | <li className="todo" style={{ opacity: deleteMutation.isMutating || updateMutation.isMutating ? 0.5 : 1 }}> |
| ce83445 | 26 | {!editing && ( |
| ce83445 | 27 | <> |
| ce83445 | 28 | <input type="checkbox" /> |
| f07784d | 29 | <div className="text"> |
| ce83445 | 30 | <p>{item.text}</p> |
| ce83445 | 31 | <p className="timestamp">{item.createdAt}</p> |
| ce83445 | 32 | </div> |
| ce83445 | 33 | <button className="edit-button" title="Edit" onClick={() => setEditing(true)}> |
| ce83445 | 34 | ✏️ |
| ce83445 | 35 | </button> |
| f07784d | 36 | <button className="delete-button" title="Delete" onClick={() => deleteMutation.mutate(item.id)}> |
| ce83445 | 37 | 🗑️ |
| ce83445 | 38 | </button> |
| ce83445 | 39 | </> |
| ce83445 | 40 | )} |
| ce83445 | 41 | {editing && ( |
| ce83445 | 42 | <form onSubmit={handleSubmit(updateMutation.mutate)}> |
| f07784d | 43 | <TextField isRequired isReadOnly={updateMutation.isMutating} isDisabled={updateMutation.isMutating}> |
| ce83445 | 44 | <Input {...register("text")} defaultValue={item.text} /> |
| ce83445 | 45 | {/* {err?.text && <p>{err.text._errors[0]}</p>} */} |
| ce83445 | 46 | </TextField> |
| ce83445 | 47 | <button |
| ce83445 | 48 | type="submit" |
| ce83445 | 49 | className="edit-button" |
| ce83445 | 50 | title="Save" |
| ce83445 | 51 | disabled={updateMutation.isMutating} |
| ce83445 | 52 | > |
| ce83445 | 53 | 💾 |
| ce83445 | 54 | </button> |
| ce83445 | 55 | <button |
| ce83445 | 56 | className="delete-button" |
| ce83445 | 57 | title="Cancel" |
| ce83445 | 58 | onClick={() => { |
| ce83445 | 59 | reset({ text: item.text }); |
| ce83445 | 60 | setEditing(false); |
| ce83445 | 61 | }} |
| ce83445 | 62 | disabled={updateMutation.isMutating} |
| ce83445 | 63 | > |
| ce83445 | 64 | 🚫 |
| ce83445 | 65 | </button> |
| ce83445 | 66 | </form> |
| ce83445 | 67 | )} |
| ce83445 | 68 | </li> |
| ce83445 | 69 | ); |
| ce83445 | 70 | }; |
| ce83445 | 71 | |
| ce83445 | 72 | export default Todo; |