Первый хук с которого начнем это useTransition
. Он используется для обработки состояния ожидания.
Хук useTransition возвращает:
const [isPending, startTransition] = useTransition();
useTransition(async () => {
// code to handle form submitting
})
return (
// ...
<button onClick={handleSubmit} disabled={isPending}>
Update
</button>
// ...
)
То есть теперь вместо состояния const [isPending, setIsPending] = useState(false);
которое мы вручную меняли сначала на true
, а по завершению работы асинхронной функции на false
, мы можем использовать хук useTransition()
.
Хук useTransition()
автоматически следит за выполнением асинхронной функции переданной в startTransition()
. Когда она стартовала - переводит isPending
в true
, а по её завершению - в false
.
Это избавляет нас от необходимости вручную управлять состоянием загрузки.
Вот как это выглядит:
const [isPending, setTransition] = useTransition();
const handleSubmit = () => {
setTransition( async ()=>{
const error = await updateName(name);
if (error) {
setError(error);
return;
}
setSuccess(true);
})
};
return (
<button onClick={handleSubmit} disabled={isPending}>
Update
</button>
)
Полный код компонента:
import { useState, useTransition } from "react";
async function updateName() {
await new Promise((resolve) => {
setTimeout(() => {
resolve();
}, 2000);
});
console.log("Name updated!");
}
function App() {
const [name, setName] = useState("");
const [error, setError] = useState(null);
const [isPending, setTransition] = useTransition();
const [success, setSuccess] = useState(false)
const handleSubmit = () => {
setTransition( async ()=>{
const error = await updateName(name);
if (error) {
setError(error);
return;
}
setSuccess(true);
})
};
function showSuccess(){
return (
<div className="alert alert-success mb-3">
Form submited!
</div>
);
}
return (
<div className="card shadow p-3">
{success && showSuccess()}
<label className="form-label">Enter name</label>
<input
className="form-control mb-3"
value={name}
onChange={(event) => setName(event.target.value)}
/>
<button
className="btn btn-dark"
onClick={handleSubmit}
disabled={isPending}
>
Update
</button>
{error && <p>{error}</p>}
</div>
);
}
export default App;
Как видите, код стал намного чище. Мы избавились от ручного управления состоянием загрузки, и теперь React сам заботится об этом через хук useTransition.
<aside> 💡
Примечание
По соглашению функции, использующие асинхронные переходы, называются «actions»
Actions функции автоматически управляют отправкой данных для вас:
useOptimistic
<form>
элементы теперь поддерживают передачу функций в свойства action
и formAction
. Переданная action функция используется как обработчик формы по умолчанию и сбрасывает форму после отправки.О actions мы поговорим далее </aside>