这是使用React Query与TypeScript的系列文章中的另一篇文章。
以前的帖子:
这篇文章涵盖了如何使用React Query来进行数据更新的请求。我们将建立一个表单,当提交时将会发出一个PUT HTTP请求。
一个人的表单
我们的表单如下:
export function App() {
return (
<div>
<form>
<p>ID:</p>
<fieldset>
<div>
<label htmlFor="firstName">First name</label>
<input
type="text"
id="firstName"
name="firstName"
/>
</div>
<div>
<label htmlFor="lastName">Last name</label>
<input
type="text"
id="lastName"
name="lastName"
/>
</div>
</fieldset>
<button type="submit">Save</button>
</form>
</div>
);
}
这个表单包含了捕捉名字和姓氏的字段。
我们希望表单包含现有的数据,以便用户可以进行任何必要的修改。我们将使用React Query来管理获取现有数据的请求。下面是查询的内容:
export function App() {
const { status: queryStatus, error: queryError, data } = useQuery<
Person,
Error
>(["person", { id: 1 }], getPerson);
if (queryStatus === "loading") {
return <div>...</div>;
}
if (queryStatus === "error") {
return <div>{queryError!.message}</div>;
}
...
}
我们对状态变量进行了别名,这样它们就不会与以后会出现的状态变量发生冲突。一个人的类型是:
type Person = {
id: number;
firstName: string;
lastName: string;
};
1 我们从获取函数getPerson ,请求人的类型为id 。这里是取数函数:
async function getPerson({ queryKey }: { queryKey: [string, { id: number }] }) {
const [, { id }] = queryKey;
const response = await fetch(`http://localhost:3004/people/${id}`);
if (!response.ok) {
throw Error("Problem fetching person");
}
const data = await response.json();
assertIsPerson(data);
return data;
}
fetch 是用来进行请求的,如果响应不成功就会抛出一个错误。
获取函数预计将返回我们想在组件中使用的响应数据。我们使用一个叫做assertIsPerson 的类型断言函数来确保数据的类型正确:
function assertIsPerson(data: any): asserts data is Person {
if (!("id" in data && "firstName" in data && "lastName" in data)) {
throw new Error("Not a person");
}
}
我们可以使用来自查询的状态变量,如下所示:
export function App() {
...
return (
<div>
{data && ( <form>
<p>ID: {data.id}</p> <fieldset>
<div>
<label htmlFor="firstName">First name</label>
<input
type="text"
id="firstName"
name="firstName"
defaultValue={data.firstName} />
</div>
<div>
<label htmlFor="lastName">Last name</label>
<input
type="text"
id="lastName"
name="lastName"
defaultValue={data.lastName} />
</div>
</fieldset>
<button type="submit">Save</button>
</form>
)} </div>
);
}
我们显示这个人的ID,并将输入值默认为这个人的名字和姓氏。
让我们开始实现表单的提交:
export function App() {
...
function handleSubmit(e: React.FormEvent<HTMLFormElement>) { e.preventDefault(); const formData = new FormData(e.target as HTMLFormElement); const firstName = formData.get("firstName") as string; const lastName = formData.get("lastName") as string; } return (
<div>
{data && (
<form onSubmit={handleSubmit}> ...
</form>
)}
</div>
);
}
提交处理程序从表单中提取姓和名的值。我们将在后面完成这个实现。
声明一个突变
React Query可以管理一个更新数据的请求,使用一个 useMutation钩子。
让我们在查询下面声明我们的突变:
export function App() {
...
const { mutate, status: mutateStatus, error: mutateError } = useMutation<
Person, // return type
Error,
Person // params type
>(updatePerson);
...
}
我们对去结构化的状态变量进行了别名,这样它们就不会与查询中的变量发生冲突。
解除结构化的mutate 变量是我们最终要用来触发更新的东西。
useMutation 在我们的例子中,我们需要一个突变函数来提出请求,也就是 。我们稍后会看一下这个。updatePerson
useMutation 接受通用类型的参数。有各种重载,但我们已经传入了以下内容:
- 突变函数的返回类型。
- 来自突变函数的错误类型。
- 突变函数的参数类型。
使用突变状态变量
我们可以以如下形式使用突变状态变量:
<form onSubmit={handleSubmit}>
<p>ID: {data.id}</p>
<fieldset disabled={mutateStatus === "loading"}> ...
</fieldset>
<button type="submit">Save</button>
{mutateStatus === "success" && <p>Change successfully saved</p>} {mutateStatus === "error" && <p>{mutateError!.message}</p>}</form>
我们在更新过程中禁用更新。当更新完成后,我们也会显示成功/错误信息。
触发突变
我们可以在提交处理程序中触发突变,如下所示:
function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
const formData = new FormData(e.target as HTMLFormElement);
const firstName = formData.get("firstName") as string;
const lastName = formData.get("lastName") as string;
mutate({ id: data!.id, firstName, lastName });}
如果我们给这个表单一个尝试,更新就成功了。

很好 😊
本帖的代码可在以下gist中找到:https://gist.github.com/carlrip/c048b9cad627fde1836a55ac24a31474