The problem
Fetching inside a component after it mounts causes render then fetch waterfalls: the view appears empty, then triggers a request, then re renders. Nested components compound the delay.
Route loaders
A loader runs as part of navigation, before or alongside rendering. The router starts fetching as soon as the destination is known, so data and code load in parallel.
- The loader receives the route params.
- It returns data the component reads synchronously.
- Errors can route to a dedicated error view.
Pending states
Because loading is tied to navigation, the router knows when a transition is pending. You can show a global progress bar or keep the old page until the new data is ready.
Why it matters
Moving fetches to the route level removes waterfalls, enables parallel loading, and gives a single place to handle errors and pending UI.
Key idea
Route loaders fetch data during navigation in parallel with code, eliminating render then fetch waterfalls.