操作
本页内容

操作

数据变异通过路由操作(Route actions)完成。操作完成后,页面上的所有加载器数据都会重新验证,以确保您的 UI 与数据保持同步,无需编写任何代码来执行此操作。

使用action定义的路由操作仅在服务器端调用,而使用clientAction定义的操作则在浏览器中运行。

客户端操作

客户端操作仅在浏览器中运行,并且在同时定义服务器操作和客户端操作时,客户端操作优先。

// route('/projects/:projectId', './project.tsx')
import type { Route } from "./+types/project";
import { Form } from "react-router";
import { someApi } from "./api";

export async function clientAction({
  request,
}: Route.ClientActionArgs) {
  let formData = await request.formData();
  let title = await formData.get("title");
  let project = await someApi.updateProject({ title });
  return project;
}

export default function Project({
  actionData,
}: Route.ComponentProps) {
  return (
    <div>
      <h1>Project</h1>
      <Form method="post">
        <input type="text" name="title" />
        <button type="submit">Submit</button>
      </Form>
      {actionData ? (
        <p>{actionData.title} updated</p>
      ) : null}
    </div>
  );
}

服务器操作

服务器操作仅在服务器端运行,并且从客户端包中移除。

// route('/projects/:projectId', './project.tsx')
import type { Route } from "./+types/project";
import { Form } from "react-router";
import { fakeDb } from "../db";

export async function action({
  request,
}: Route.ActionArgs) {
  let formData = await request.formData();
  let title = await formData.get("title");
  let project = await fakeDb.updateProject({ title });
  return project;
}

export default function Project({
  actionData,
}: Route.ComponentProps) {
  return (
    <div>
      <h1>Project</h1>
      <Form method="post">
        <input type="text" name="title" />
        <button type="submit">Submit</button>
      </Form>
      {actionData ? (
        <p>{actionData.title} updated</p>
      ) : null}
    </div>
  );
}

调用操作

操作可以通过<Form>声明式调用,也可以通过useSubmit(或<fetcher.Form>fetcher.submit)命令式调用,方法是引用路由的路径和“post”方法。

使用表单调用操作

import { Form } from "react-router";

function SomeComponent() {
  return (
    <Form action="/projects/123" method="post">
      <input type="text" name="title" />
      <button type="submit">Submit</button>
    </Form>
  );
}

这将导致导航,并在浏览器历史记录中添加一个新条目。

使用useSubmit调用操作

您可以使用useSubmit命令式地将表单数据提交给操作。

import { useCallback } from "react";
import { useSubmit } from "react-router";
import { useFakeTimer } from "fake-lib";

function useQuizTimer() {
  let submit = useSubmit();

  let cb = useCallback(() => {
    submit(
      { quizTimedOut: true },
      { action: "/end-quiz", method: "post" }
    );
  }, []);

  let tenMinutes = 10 * 60 * 1000;
  useFakeTimer(tenMinutes, cb);
}

这将导致导航,并在浏览器历史记录中添加一个新条目。

使用fetcher调用操作

Fetcher允许您将数据提交给操作(和加载器),而不会导致导航(浏览器历史记录中没有新条目)。

import { useFetcher } from "react-router";

function Task() {
  let fetcher = useFetcher();
  let busy = fetcher.state !== "idle";

  return (
    <fetcher.Form method="post" action="/update-task/123">
      <input type="text" name="title" />
      <button type="submit">
        {busy ? "Saving..." : "Save"}
      </button>
    </fetcher.Form>
  );
}

它们还具有命令式submit方法。

fetcher.submit(
  { title: "New Title" },
  { action: "/update-task/123", method: "post" }
);

有关更多信息,请参阅使用Fetcher指南。


下一步:导航

文档和示例 CC 4.0