・This pattern enables you to update the UI synchronously with useOptimistic hook while an async operation is pending, such as data fetching. This makes the app feel faster and more responsive by showing alternative UI before the server data is fetched.
import { useState, useOptimistic, useTransition } from "react";
async function saveTodo(todo) {
await new Promise((resolve) => setTimeout(resolve, 1000));
return todo;
}
function App() {
const [todos, setTodos] = useState(["Learn ReactJs", "Learn NextJs"]);
const [newTodo, setNewTodo] = useState("");
const [isPending, startTransition] = useTransition();
const [optimisticTodos, addOptimisticTodo] = useOptimistic(
todos,
(state, newTodo) => [...state, newTodo],
);
const handleSubmit = async (e) => {
e.preventDefault();
if (!newTodo.trim()) return;
startTransition(async () => {
addOptimisticTodo(newTodo);
try {
await saveTodo(newTodo);
startTransition(() => {
setTodos((prev) => [...prev, newTodo]);
setNewTodo("");
});
} catch (error) {
console.error("Failed to save todo");
}
});
};
return (
<div>
<form onSubmit={handleSubmit}>
<input
type="text"
disabled={isPending}
value={newTodo}
onChange={(e) => setNewTodo(e.target.value)}
placeholder="Add a todo"
/>
<button type="submit">Add</button>
</form>
<ul>
{optimisticTodos.map((todo, index) => (
<li key={index}>{todo}</li>
))}
</ul>
</div>
);
}
export default App;
Top comments (0)