useOptimistic
Стартовый код. Форма которая меняет имя, и это занимает 3 секунды.
import { useState } from "react";
async function updateName(name) {
console.log("updateName name:", name);
console.log("Waiting 3 sec...");
await new Promise((resolve) => {
setTimeout(() => {
resolve();
}, 3000);
});
console.log("updateName COMPLETE");
return name;
}
function App() {
const [name, setName] = useState("John");
async function handleSubmit(formData) {
const newName = await updateName(formData.get("name"));
setName(newName);
}
return (
<form action={handleSubmit} className="card shadow p-3">
<p className="fs-3">Current name: {name}</p>
<label className="form-label">Enter name</label>
<input name="name" className="form-control mb-3" />
<button className="btn btn-dark">Update</button>
</form>
);
}
export default App;
Хук useOptimistic
позволяет показать оптимистичный результат, не дожидаясь завершения выполнения action функции обработчика формы.
const [optimisticState, addOptimistic] = useOptimistic(state, updateFn);
Код с использованием хука:
import { useState, useOptimistic } from "react";
async function updateName(name) {
console.log("updateName name:", name);
console.log("Waiting 3 sec...");
await new Promise((resolve) => {
setTimeout(() => {
resolve();
}, 3000);
});
console.log("updateName COMPLETE");
return name;
}
function App() {
const [name, setName] = useState("John");
const [optimisticState, setOptimisticState] = useOptimistic(name);
async function handleSubmit(formData) {
setOptimisticState(formData.get("name"));
const newName = await updateName(formData.get("name"));
setName(newName);
}
return (
<form action={handleSubmit} className="card shadow p-3">
<p className="fs-3">Current name: {optimisticState}</p>
<label className="form-label">Enter name</label>
<input name="name" className="form-control mb-3" />
<button
className="btn btn-dark"
disabled={name !== optimisticState}
>
Update
</button>
</form>
);
}
export default App;
Использование updateFn
в useOptimistic()
Тут рассмотрим пример из офф документации.
optimisticMessages
содержит оптимистичное состояние, сформированное через updateFn
.messages
. Это происходит автоматически, так как useOptimistic
обновляет свои данные при изменении messages
.import { useOptimistic, useState, useRef } from "react";
async function deliverMessage(message) {
await new Promise((res) => setTimeout(res, 4000));
return message;
}
function Thread({ messages, sendMessage }) {
const formRef = useRef();
async function formAction(formData) {
addOptimisticMessage(formData.get("message"));
formRef.current.reset();
await sendMessage(formData);
}
const [optimisticMessages, addOptimisticMessage] = useOptimistic(
messages,
(state, newMessage) => [
...state,
{
text: newMessage,
sending: true,
},
]
);
return (
<>
{optimisticMessages.map((message, index) => (
<div key={index} className="mb-1">
{message.text}
{!!message.sending && <small> (Sending...)</small>}
</div>
))}
<form action={formAction} ref={formRef}>
<input
type="text"
name="message"
placeholder="Hello!"
className="form-control mb-3"
/>
<button type="submit" className="btn btn-dark">
Send
</button>
</form>
</>
);
}
export default function App() {
const [messages, setMessages] = useState([
{ text: "Hello there!", sending: false, key: 1 },
]);
async function sendMessage(formData) {
const sentMessage = await deliverMessage(formData.get("message"));
setMessages((messages) => [...messages, { text: sentMessage }]);
}
return <Thread messages={messages} sendMessage={sendMessage} />;
}