前言
React19发布也有一段时间了,其中,最引人注目的便是三个新的 Hooks,它们已经稳定发布并准备好投入实际开发中。对于开发者来说,这些新功能不仅能简化代码,还能提升应用的性能和用户体验。接下来,我将详细介绍这三个新的 Hooks 及其应用场景。
useActionState
useFormStatus
useOptimistic
这三个 Hooks 为 React 的状态管理、表单处理和异步操作提供了更加简洁且功能强大的方式。尤其是 useActionState
,它结合了 useTransition
和 useReducer
的优势,能够处理复杂的异步操作和状态更新逻辑,简化了传统的实现方式,并使得状态管理更加清晰高效。
在这篇文章中,我们将深入探讨这些新 Hooks 的使用方法,结合实际的代码示例来展示它们如何简化开发过程、提高代码的可维护性和可读性,同时也会对比 React 19 之前的实现方式,帮助大家更好地理解这些新特性所带来的变化和提升。如果你想跟上 React 生态的最新进展,掌握这些新功能是非常必要的。
useActionState
useActionState
是一个在需要利用操作执行结果的场景中使用的Hook。
它结合了以执行操作为目的的useTransition
和以管理状态为目的的useReducer
的功能。
实现示例
以前的实现方式
在React19之前,通常会使用useState
等方法来实现加载状态的显示以及表单值的管理。例如:
import React, { useState, useCallback, FormEvent } from "react";
const updateName = async (name: string) => {
return new Promise<string>((resolve) => {
setTimeout(() => resolve(name), 3000);
});
};
export default function UseStateDemo() {
const [name, setName] = useState<string>("");
const [isPending, setIsPending] = useState<boolean>(false);
const handleSubmit = useCallback(
async (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
const formData = new FormData(event.currentTarget);
const inputName = formData.get("name") as string;
setIsPending(true);
const newName = await updateName(inputName);
if (newName) {
setName(newName);
}
setIsPending(false);
},
[]
);
return (
<div className="mt-10">
<h1 className="flex justify-center text-xl">useActionState</h1>
<form
action={handleSubmit}
className="space-y-4 p-6 shadow-md max-w-md mx-auto"
>
<div className="flex flex-col">
<input
type="text"
name="name"
className="border border-gray-300 p-2"
/>
</div>
<button
type="submit"
disabled={isPending}
className={`w-full py-2 px-4 text-white ${
isPending
? "bg-emerald-400"
: "bg-emerald-600 hover:bg-emerald-700 focus:ring-emerald-500"
}`}
>
{isPending ? "Updating..." : "Update"}
</button>
{isPending && <p>Loading...</p>}
{name && <p>{name}</p>}
</form>
</div>
);
}
使用useActionState
的实现方式
与上面的代码相比,这种实现更加高效,非常方便!
import { useActionState } from "react";
const updateName = async (name: string) => {
return new Promise<string>((resolve) => {
setTimeout(() => resolve(name), 3000);
});
};
export default function UseActionStateDemo() {
const [name, submitAction, isPending] = useActionState(
async (prevState: string, formData: FormData) => {
console.log("prevState : " + prevState);
const newName = await updateName(formData.get("name") as string);
if (!newName) {
return "";
}
return newName;
},
"aaa"
);
return (
<div className="mt-10">
<h1 className="flex justify-center text-xl">useActionState</h1>
<form
action={submitAction}
className="space-y-4 p-6 shadow-md max-w-md mx-auto"
>
<div className="flex flex-col">
<input
type="text"
name="name"
className="border border-gray-300 p-2"
/>
</div>
<button
type="submit"
disabled={isPending}
className={`w-full py-2 px-4 text-white ${
isPending
? "bg-emerald-400"
: "bg-emerald-600 hover:bg-emerald-700 focus:ring-emerald-500"
}`}
>
{isPending ? "Updating..." : "Update"}
</button>
{isPending && <p>Loading...</p>}
{name && <p>{name}</p>}
</form>
</div>
);
}
useFormStatus
useFormStatus
是一个允许在表单提交后向用户显示处理状态的Hook。
正确的实现方式
在表单内部的组件中定义useFormStatus
。例如:
import { useFormStatus } from "react-dom";
function Submit() {
const { pending } = useFormStatus();
return (
<button
type="submit"
disabled={pending}
className="bg-blue-500 text-white py-2 px-4 rounded-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
>
{pending ? "Submitting..." : "Submit"}
</button>
);
}
async function updateName() {
await new Promise((resolve) => setTimeout(resolve, 3000));
}
function Form({ action }: { action: () => void }) {
return (
<form action={action}>
<Submit />
</form>
);
}
export const UseFormStatusDemo = () => {
return (
<div className="mt-10 flex justify-center">
<Form action={() => updateName()} />
</div>
);
};
useOptimistic
useOptimistic
是一个实现乐观UI更新的Hook。乐观UI更新指的是在实际处理完成之前,提前向用户显示完成后的状态。
示例实现
输入文本后,点击提交按钮会先以红色文字显示,然后在3秒后以蓝色文字显示。
import { useOptimistic, useState } from "react";
async function updateName(name: string) {
await new Promise((resolve) => setTimeout(resolve, 3000));
return name;
}
export const UseOptimisticDemo = () => {
const [name, setName] = useState("");
const [optimisticName, setOptimisticName] = useOptimistic("");
const submitAction = async (formData: FormData) => {
const newName = formData.get("name") as string;
setOptimisticName(newName);
const updatedName = await updateName(newName);
await setName(updatedName);
};
return (
<div className="mt-10">
<h1 className="flex justify-center font-bold text-xl">useOptimistic</h1>
<form
action={submitAction}
className="space-y-4 bg-white p-6 shadow-md max-w-md mx-auto"
>
<div className="flex flex-col">
<input
type="text"
name="name"
className="border border-gray-300"
disabled={"" !== optimisticName}
/>
</div>
<button type="submit" className="bg-blue-500 text-white py-2 px-4">
Submit
</button>
</form>
<p className="mt-4 text-center">
Your name is:{" "}
<span className="font-semibold text-red-500">{optimisticName}</span>
<span className="font-semibold text-blue-500">{name}</span>
</p>
</div>
);
};
总结
React19新增的Hooks都非常实用,特别是useActionState
,在未来的项目中会变得非常流行,并且会成为开发者处理异步操作和状态更新的必备工具。
评论(0)