You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
50 lines
1.2 KiB
TypeScript
50 lines
1.2 KiB
TypeScript
import { useState } from "react";
|
|
import { useTRPCClient } from "../../trpc/client";
|
|
|
|
export function TodoList({
|
|
initialTodoItems,
|
|
}: {
|
|
initialTodoItems: { text: string }[];
|
|
}) {
|
|
const [todoItems, setTodoItems] = useState(initialTodoItems);
|
|
const [newTodo, setNewTodo] = useState("");
|
|
const trpc = useTRPCClient();
|
|
|
|
return (
|
|
<>
|
|
<ul>
|
|
{todoItems.map((todoItem, index) => (
|
|
// biome-ignore lint:
|
|
<li key={index}>{todoItem.text}</li>
|
|
))}
|
|
</ul>
|
|
<div>
|
|
<form
|
|
onSubmit={async (ev) => {
|
|
ev.preventDefault();
|
|
if (newTodo.trim() === "") return;
|
|
|
|
// Optimistic UI update
|
|
setTodoItems((prev) => [...prev, { text: newTodo }]);
|
|
try {
|
|
await trpc.onNewTodo.mutate(newTodo);
|
|
setNewTodo("");
|
|
} catch (e) {
|
|
console.error(e);
|
|
// rollback
|
|
setTodoItems((prev) => prev.slice(0, -1));
|
|
}
|
|
}}
|
|
>
|
|
<input
|
|
type="text"
|
|
onChange={(ev) => setNewTodo(ev.target.value)}
|
|
value={newTodo}
|
|
/>
|
|
<button type="submit">Add to-do</button>
|
|
</form>
|
|
</div>
|
|
</>
|
|
);
|
|
}
|