用React查询更新请求的详细指南

303 阅读3分钟

这是使用React Query与TypeScript的系列文章中的另一篇文章。

以前的帖子:

这篇文章涵盖了如何使用React Query来进行数据更新的请求。我们将建立一个表单,当提交时将会发出一个PUT HTTP请求。

Update reqeusts 一个人的表单

我们的表单如下:

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 接受通用类型的参数。有各种重载,但我们已经传入了以下内容:

  1. 突变函数的返回类型。
  2. 来自突变函数的错误类型。
  3. 突变函数的参数类型。

使用突变状态变量

我们可以以如下形式使用突变状态变量:

<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 });}

如果我们给这个表单一个尝试,更新就成功了。

Successful update

很好 😊

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