You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: docs/guides/optimistic-ui.md
+2-2
Original file line number
Diff line number
Diff line change
@@ -11,8 +11,8 @@ Remix can help you build optimistic UI with [`useNavigation`][use-navigation] an
11
11
## Strategy
12
12
13
13
1. User submits a form (or you do with [`useSubmit`][use-submit] or [`fetcher.submit`][fetcher-submission]).
14
-
2. Remix makes the submission and its data immediately available to you on [`navigation.formData`][navigation-formdata] or [`fetcher.submission`][fetcher-submission].
15
-
3. App uses [`submission.formData`][form-data] to render an optimistic version of _what it will render_ when the submission completes successfully.
14
+
2. Remix makes the submission and its data immediately available to you on [`navigation.formData`][navigation-formdata] or [`fetcher.formData`][fetcher-submission].
15
+
3. App uses [`formData`][form-data] to render an optimistic version of _what it will render_ when the submission completes successfully.
16
16
4. Remix automatically revalidates all the data.
17
17
- If successful, the user doesn't even notice.
18
18
- If it fails, the page data is automatically in sync with the server so the UI reverts automatically.
Copy file name to clipboardexpand all lines: docs/hooks/use-fetcher.md
+59-20
Original file line number
Diff line number
Diff line change
@@ -44,8 +44,10 @@ function SomeComponent() {
44
44
45
45
// build UI with these
46
46
fetcher.state;
47
-
fetcher.type;
48
-
fetcher.submission;
47
+
fetcher.formMethod;
48
+
fetcher.formAction;
49
+
fetcher.formData;
50
+
fetcher.formEncType;
49
51
fetcher.data;
50
52
}
51
53
```
@@ -71,6 +73,8 @@ You can know the state of the fetcher with `fetcher.state`. It will be one of:
71
73
72
74
#### `fetcher.type`
73
75
76
+
<docs-error>`fetcher.type` is deprecated and will be removed in v2.</docs-error>
77
+
74
78
This is the type of state the fetcher is in. It's like `fetcher.state`, but more granular. Depending on the fetcher's state, the types can be the following:
75
79
76
80
-`state === "idle"`
@@ -89,8 +93,47 @@ This is the type of state the fetcher is in. It's like `fetcher.state`, but more
89
93
-**actionRedirect** - The action from an "actionSubmission" returned a redirect and the page is transitioning to the new location.
90
94
-**normalLoad** - A route's loader is being called without a submission (`fetcher.load()`).
91
95
96
+
##### Moving away from `fetcher.type`
97
+
98
+
The `type` field has been been deprecated and will be removed in v2. We've found that `state` is sufficient for almost all use-cases, and when it's not you can derive sub-types via `fetcher.state` and other fields. Here's a few examples:
99
+
100
+
```js
101
+
functionComponent() {
102
+
let fetcher =useFetcher();
103
+
104
+
let isDone =
105
+
fetcher.state==="idle"&&fetcher.data!=null;
106
+
107
+
let isActionSubmission =fetcher.state==="submitting";
108
+
109
+
let isActionReload =
110
+
fetcher.state==="loading"&&
111
+
fetcher.formMethod!=null&&
112
+
fetcher.formMethod!="get"&&
113
+
// If we returned data, we must be reloading
114
+
fetcher.data!=null;
115
+
116
+
let isActionRedirect =
117
+
fetcher.state==="loading"&&
118
+
fetcher.formMethod!=null&&
119
+
navigation.formMethod!="get"&&
120
+
// If we have no data we must have redirected
121
+
fetcher.data==null;
122
+
123
+
let isLoaderSubmission =
124
+
navigation.state==="loading"&&
125
+
navigation.state.formMethod==="get";
126
+
127
+
let isNormalLoad =
128
+
navigation.state==="loading"&&
129
+
navigation.state.formMethod==null;
130
+
}
131
+
```
132
+
92
133
#### `fetcher.submission`
93
134
135
+
<docs-error>`fetcher.submission` is deprecated and will be removed in v2. Instead, the fields inside of `submission` have been flattened onto the `fetcher` itself (`fetcher.formMethod`, `fetcher.formAction`, `fetcher.formData`, `fetcher.formEncType`)</docs-error>
136
+
94
137
When using `<fetcher.Form>` or `fetcher.submit()`, the form submission is available to build optimistic UI.
95
138
96
139
It is not available when the fetcher state is "idle" or "loading".
@@ -153,7 +196,7 @@ function SomeComponent() {
153
196
const fetcher =useFetcher();
154
197
155
198
useEffect(() => {
156
-
if (fetcher.type==="init") {
199
+
if (fetcher.state==="idle"&&fetcher.data==null) {
157
200
fetcher.load("/some/route");
158
201
}
159
202
}, [fetcher]);
@@ -204,7 +247,10 @@ function NewsletterSignup() {
204
247
const ref =useRef();
205
248
206
249
useEffect(() => {
207
-
if (newsletter.type==="done"&&newsletter.data.ok) {
250
+
if (
251
+
newsletter.state==="idle"&&
252
+
newsletter.data?.ok
253
+
) {
208
254
ref.current.reset();
209
255
}
210
256
}, [newsletter]);
@@ -225,7 +271,7 @@ function NewsletterSignup() {
225
271
</button>
226
272
</p>
227
273
228
-
{newsletter.type==="done"? (
274
+
{newsletter.state==="idle"&&newsletter.data? (
229
275
newsletter.data.ok? (
230
276
<p>Thanks for subscribing!</p>
231
277
) :newsletter.data.error? (
@@ -283,18 +329,12 @@ export function NewsletterSignup() {
283
329
Form={newsletter.Form}
284
330
data={newsletter.data}
285
331
state={newsletter.state}
286
-
type={newsletter.type}
287
332
/>
288
333
);
289
334
}
290
335
291
336
// used here and in the route
292
-
exportfunction NewsletterForm({
293
-
Form,
294
-
data,
295
-
state,
296
-
type,
297
-
}) {
337
+
exportfunction NewsletterForm({ Form, data, state }) {
298
338
// refactor a bit in here, just read from props instead of useFetcher
299
339
}
300
340
```
@@ -309,12 +349,7 @@ import { NewsletterForm } from "~/NewsletterSignup";
Copy file name to clipboardexpand all lines: docs/hooks/use-fetchers.md
+8-8
Original file line number
Diff line number
Diff line change
@@ -27,14 +27,14 @@ For example, imagine a UI where the sidebar lists projects, and the main view di
27
27
+-----------------+----------------------------┘
28
28
```
29
29
30
-
When the user clicks a checkbox, the submission goes to the action to change the state of the task. Instead of creating a "loading state" we want to create an "optimistic UI" that will **immediately** update the checkbox to appear checked even though the server hasn't processed it yet. In the checkbox component, we can use `fetcher.submission`:
30
+
When the user clicks a checkbox, the submission goes to the action to change the state of the task. Instead of creating a "loading state" we want to create an "optimistic UI" that will **immediately** update the checkbox to appear checked even though the server hasn't processed it yet. In the checkbox component, we can use `fetcher.formData`:
0 commit comments