UNPKG

3.2 kB Markdown View Raw
1---
2title: Actions
3order: 5
4---
5
6# Actions
7
8[MODES: data]
9
10## Defining Actions
11
12Data mutations are done through Route actions defined on the `action` property of a route object. When the action completes, all loader data on the page is revalidated to keep your UI in sync with the data without writing any code to do it.
13
14```tsx
15import { createBrowserRouter } from "react-router";
16import { someApi } from "./api";
17
18let router = createBrowserRouter([
19 {
20 path: "/projects/:projectId",
21 Component: Project,
22 action: async ({ request }) => {
23 let formData = await request.formData();
24 let title = formData.get("title");
25 let project = await someApi.updateProject({ title });
26 return project;
27 },
28 },
29]);
30```
31
32## Calling Actions
33
34Actions are called declaratively through `<Form>` and imperatively through `useSubmit` (or `<fetcher.Form>` and `fetcher.submit`) by referencing the route's path and a "post" method.
35
36### Calling actions with a Form
37
38```tsx
39import { Form } from "react-router";
40
41function SomeComponent() {
42 return (
43 <Form action="/projects/123" method="post">
44 <input type="text" name="title" />
45 <button type="submit">Submit</button>
46 </Form>
47 );
48}
49```
50
51This will cause a navigation and a new entry will be added to the browser history.
52
53### Calling actions with useSubmit
54
55You can submit form data to an action imperatively with `useSubmit`.
56
57```tsx
58import { useCallback } from "react";
59import { useSubmit } from "react-router";
60import { useFakeTimer } from "fake-lib";
61
62function useQuizTimer() {
63 let submit = useSubmit();
64
65 let cb = useCallback(() => {
66 submit(
67 { quizTimedOut: true },
68 { action: "/end-quiz", method: "post" },
69 );
70 }, []);
71
72 let tenMinutes = 10 * 60 * 1000;
73 useFakeTimer(tenMinutes, cb);
74}
75```
76
77This will cause a navigation and a new entry will be added to the browser history.
78
79### Calling actions with a fetcher
80
81Fetchers allow you to submit data to actions (and loaders) without causing a navigation (no new entries in the browser history).
82
83```tsx
84import { useFetcher } from "react-router";
85
86function Task() {
87 let fetcher = useFetcher();
88 let busy = fetcher.state !== "idle";
89
90 return (
91 <fetcher.Form method="post" action="/update-task/123">
92 <input type="text" name="title" />
93 <button type="submit">
94 {busy ? "Saving..." : "Save"}
95 </button>
96 </fetcher.Form>
97 );
98}
99```
100
101They also have the imperative `submit` method.
102
103```tsx
104fetcher.submit(
105 { title: "New Title" },
106 { action: "/update-task/123", method: "post" },
107);
108```
109
110See the [Using Fetchers][fetchers] guide for more information.
111
112## Accessing Action Data
113
114Actions can return data available through `useActionData` in the route component or `fetcher.data` when using a fetcher.
115
116```tsx
117function Project() {
118 let actionData = useActionData();
119 return (
120 <div>
121 <h1>Project</h1>
122 <Form method="post">
123 <input type="text" name="title" />
124 <button type="submit">Submit</button>
125 </Form>
126 {actionData ? (
127 <p>{actionData.title} updated</p>
128 ) : null}
129 </div>
130 );
131}
132```
133
134---
135
136Next: [Navigating](./navigating)
137
138[fetchers]: ../../how-to/fetchers