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
When building web applications, managing network requests can be a daunting task. The challenges of ensuring up-to-date data and handling simultaneous requests often lead to complex logic in the application to deal with interruptions and race conditions. Remix simplifies this process by automating network management, mirroring and expanding the intuitive behavior of web browsers.
7
+
When building web applications, managing network requests can be a daunting task. The challenges of ensuring up-to-date data and handling simultaneous requests often lead to complex logic in the application to deal with interruptions and race conditions. Remix simplifies this process by automating network management, mirroring, and expanding the intuitive behavior of web browsers.
8
8
9
9
To help understand how Remix works, remember from [Fullstack Data Flow][fullstack_data_flow] that after `form` submissions, Remix will fetch fresh data from the loaders. This is called revalidation.
10
10
@@ -49,11 +49,11 @@ submission 2: |-----✓-----✅
49
49
submission 3: |-----✓-----✅
50
50
```
51
51
52
-
Because the revalidation from submission (2) started later and landed earlier than submission (1), the requests from submission (1) are cancelled and only the data from submission (2) is committed to the UI. It was requested later so its more likely to contain the updated values from both (1) and (2).
52
+
Because the revalidation from submission (2) started later and landed earlier than submission (1), the requests from submission (1) are canceled and only the data from submission (2) is committed to the UI. It was requested later, so it's more likely to contain the updated values from both (1) and (2).
53
53
54
54
## Potential for Stale Data
55
55
56
-
It's unlikely your users will ever experience this, but there are still chances for the user to see stale data in very rare conditions with inconsistent infrastructure. Even though Remix cancels requests for stale data, they will still end up making it to the server. Cancelling a request in the browser simply releases browser resources for that request, it can't "catch up" and stop it from getting to the server. In extremely rare conditions, a cancelled request may change data after the interrupting `action`'s revalidation lands. Consider this diagram:
56
+
It's unlikely your users will ever experience this, but there are still chances for the user to see stale data in very rare conditions with inconsistent infrastructure. Even though Remix cancels requests for stale data, they will still end up making it to the server. Cancelling a request in the browser simply releases browser resources for that request, it can't "catch up" and stop it from getting to the server. In extremely rare conditions, a canceled request may change data after the interrupting `action`'s revalidation lands. Consider this diagram:
57
57
58
58
```text
59
59
👇 interruption with new submission
@@ -120,11 +120,11 @@ export function CitySearchCombobox() {
120
120
}
121
121
```
122
122
123
-
All the application needs to know is how to query the data and how to render it, Remix handles the network.
123
+
All the application needs to know is how to query the data and how to render it; Remix handles the network.
124
124
125
125
## Conclusion
126
126
127
-
Remix offers developers an intuitive, browser-based approach to managing network requests. By mirroring browser behaviors and enhancing them where needed, it simplifies the complexities of concurrency, revalidation, and potential race conditions. Whether you're building a simple webpage or a sophisticated web application, Remix ensures that your user interactions are smooth, reliable, and always up-to-date.
127
+
Remix offers developers an intuitive, browser-based approach to managing network requests. By mirroring browser behaviors and enhancing them where needed, it simplifies the complexities of concurrency, revalidation, and potential race conditions. Whether you're building a simple webpage or a sophisticated web application, Remix ensures that your user interactions are smooth, reliable, and always up to date.
Copy file name to clipboardExpand all lines: docs/discussion/form-vs-fetcher.md
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -134,7 +134,7 @@ Combined, these APIs offer a balanced blend of structured navigation and feedbac
134
134
135
135
Now consider we're looking at a list of recipes that have delete buttons on each item. When a user clicks the delete button, we want to delete the recipe from the database and remove it from the list without navigating away from the list.
136
136
137
-
First consider the basic route setup to get a list of recipes on the page:
137
+
First, consider the basic route setup to get a list of recipes on the page:
138
138
139
139
```tsx filename=app/routes/recipes/_index.tsx
140
140
importtype { LoaderFunctionArgs } from"@remix-run/node"; // or cloudflare/deno
Using [`useFetcher`][use_fetcher] in this scenario works perfectly. Instead of navigating away or refreshing the entire page, we want in-place updates. When a user deletes a recipe, the action called and the fetcher manages the corresponding state transitions.
195
+
Using [`useFetcher`][use_fetcher] in this scenario works perfectly. Instead of navigating away or refreshing the entire page, we want in-place updates. When a user deletes a recipe, the `action` is called and the fetcher manages the corresponding state transitions.
196
196
197
197
The key advantage here is the maintenance of context. The user stays on the list when the deletion completes. The fetcher's state management capabilities are leveraged to give real-time feedback: it toggles between `"Deleting..."` and `"Delete"`, providing a clear indication of the ongoing process.
198
198
199
-
Furthermore, with each fetcher having the autonomy to manage its own state, operations on individual list items become independent, ensuring that actions on one item don't affect the others (though revalidation of the page data is a shared concern that is covered in [Network Concurrency Management][network_concurrency_management]).
199
+
Furthermore, with each `fetcher` having the autonomy to manage its own state, operations on individual list items become independent, ensuring that actions on one item don't affect the others (though revalidation of the page data is a shared concern covered in [Network Concurrency Management][network_concurrency_management]).
200
200
201
201
In essence, `useFetcher` offers a seamless mechanism for actions that don't necessitate a change in the URL or navigation, enhancing the user experience by providing real-time feedback and context preservation.
Copy file name to clipboardExpand all lines: docs/discussion/introduction.md
+7-7Lines changed: 7 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -44,7 +44,7 @@ app.all(
44
44
);
45
45
```
46
46
47
-
Express (or Node.js) is the actual server, Remix is just a handler on that server. The `"@remix-run/express"` package is called an adapter. Remix handlers are server agnostic. Adapters make them work for a specific server by converting the server's request/response API into the Fetch API on the way in, and then adapting the Fetch Response coming from Remix into the server's response API. Here's some pseudocode of what an adapter does:
47
+
Express (or Node.js) is the actual server, Remix is just a handler on that server. The `"@remix-run/express"` package is called an adapter. Remix handlers are server agnostic. Adapters make them work for a specific server by converting the server's request/response API into the Fetch API on the way in and then adapting the Fetch Response coming from Remix into the server's response API. Here's some pseudocode of what an adapter does:
48
48
49
49
```ts
50
50
exportfunction createRequestHandler({ build }) {
@@ -65,7 +65,7 @@ export function createRequestHandler({ build }) {
65
65
}
66
66
```
67
67
68
-
Real adapters do a bit more than that, but that's the gist of it. Not only does this enable you to deploy Remix anywhere, but it also lets you incrementally adopt it in an existing JavaScript server since you can have routes outside of Remix that your server continues to handle before getting to Remix.
68
+
Real adapters do a bit more than that, but that's the gist of it. Not only does this enable you to deploy Remix anywhere, it also lets you incrementally adopt it in an existing JavaScript server since you can have routes outside of Remix that your server continues to handle before getting to Remix.
69
69
70
70
Additionally, if Remix doesn't have an adapter for your server already, you can look at the source of one of the adapters and build your own.
71
71
@@ -77,7 +77,7 @@ Instead of having a split between View and Controller, Remix Route modules take
77
77
78
78
Most server-side frameworks are "model focused". A controller manages _multiple URLs_ for a single model.
79
79
80
-
Remix is _UIfocused_. Routes can handle an entire URL or just a segment of the URL. When a route maps to just a segment, the nested URL segments become nested layouts in the UI. In this way, each layout (view) can be its own controller and then Remix will aggregate the data and components to build the complete UI.
80
+
Remix is _UI-focused_. Routes can handle an entire URL or just a segment of the URL. When a route maps to just a segment, the nested URL segments become nested layouts in the UI. In this way, each layout (view) can be its own controller and then Remix will aggregate the data and components to build the complete UI.
81
81
82
82
More often than not, a Remix route module can contain both the UI and the interactions with the models in the same file, which leads to really nice developer ergonomics and productivity.
83
83
@@ -140,7 +140,7 @@ export async function action({
140
140
141
141
You can actually use Remix as just a server-side framework without using any browser JavaScript at all. The route conventions for data loading with `loader`, mutations with `action` and HTML forms, and components that render at URLs, can provide the core feature set of a lot of web projects.
142
142
143
-
In this way, **Remix scales down**. Not every page in your application needs a bunch of JavaScript in the browser and not every user interaction requires any extra flair than the browser's default behaviors. In Remix, you can build it the simple way first, and then scale up without changing the fundamental model. Additionally, the majority of the app works before JavaScript loads in the browser, which makes Remix apps resilient to choppy network conditions by design.
143
+
In this way, **Remix scales down**. Not every page in your application needs a bunch of JavaScript in the browser, and not every user interaction requires any extra flair than the browser's default behaviors. In Remix, you can build it the simple way first, and then scale up without changing the fundamental model. Additionally, the majority of the app works before JavaScript loads in the browser, which makes Remix apps resilient to choppy network conditions by design.
144
144
145
145
If you're not familiar with traditional back-end web frameworks, you can think of Remix routes as React components that are already their own API route and already know how to load and submit data to themselves on the server.
146
146
@@ -154,20 +154,20 @@ Additionally, when users submit a `<Form>` to update data, instead of doing a no
154
154
155
155
This has many performance benefits over making a full-document request:
156
156
157
-
1. Assets don't need to be re-downloaded (or pulled from cache)
157
+
1. Assets don't need to be re-downloaded (or pulled from the cache)
158
158
2. Assets don't need to be parsed by the browser again
159
159
3. The data fetched is much smaller than the entire document (sometimes orders of magnitude)
160
160
4. Because Remix enhances HTML APIs (`<a>` and `<form>`), your app tends to work even before JavaScript has loaded on the page
161
161
162
-
Remix also has some builtin optimizations for client-side navigation. It knows which layouts will persist between the two URLs, so it only fetches the data for the ones that are changing. A full document request would require all data to be fetched on the server, wasting resources on your back end and slowing down your app.
162
+
Remix also has some built-in optimizations for client-side navigation. It knows which layouts will persist between the two URLs, so it only fetches the data for the ones that are changing. A full document request would require all data to be fetched on the server, wasting resources on your back end and slowing down your app.
163
163
164
164
This approach also has UX benefits like not resetting the scroll position of a sidebar nav and allowing you to move focus to something that makes more sense than the top of the document.
165
165
166
166
Remix can also prefetch all resources for a page when the user is about to click a link. The browser framework knows about the compiler's asset manifest. It can match the URL of the link, read the manifest, and then prefetch all data, JavaScript modules, and even CSS resources for the next page. This is how Remix apps feel fast even when networks are slow.
167
167
168
168
Remix then provides client side APIs, so you can create rich user experiences without changing the fundamental model of HTML and browsers.
169
169
170
-
Taking our route module from before, here are a few small, but useful UX improvements to the form that you can only do with JavaScript in the browser:
170
+
Taking our route module from before, here are a few small but useful UX improvements to the form that you can only do with JavaScript in the browser:
171
171
172
172
1. Disable the button when the form is being submitted
173
173
2. Focus the input when server-side form validation fails
0 commit comments