The @remix-run/router package is the heart of React Router and provides all the core functionality for routing, data loading, data mutations, and navigation.
If you're using React Router, you should never import anything directly from
the @remix-run/router or react-router packages, but you should have everything
you need in either react-router-dom or react-router-native. Both of those
packages re-export everything from @remix-run/router and react-router.
A Router instance can be created using createRouter:
let router = createRouter({
// Routes array using react-router RouteObject's
routes,
// History instance
history,
// Callback function executed on every state change
onChange: (state) => { ... },
// Optional hydration data for SSR apps
hydrationData?: HydrationState;
}Internally, the Router represents the state in an object of the following format, which is available through router.state or via the onChange callback function:
interface RouterState {
// The `history` action of the most recently completed navigation
action: Action;
// The current location of the router. During a navigation this reflects
// the "old" location and is updated upon completion of the navigation
location: Location;
// The current set of route matches
matches: RouteMatch[];
// The state of the current navigation
navigation: Navigation;
// Data from the loaders for the current matches
loaderData: RouteData;
// Data from the action for the current matches
actionData: RouteData | null;
// Errors thrown from loaders/actions for the current matches
errors: RouteData | null;
}All navigations are done through the router.navigate API which is overloaded to support different types of navigations:
// Link navigation (pushes onto the history stack by default)
router.navigate('/page');
// Link navigation (replacing the history stack)
router.navigate('/page', { replace: true });
// Pop navigation (moving backward/forward in the history stack)
router.navigate(-1);
// Form navigation
router.navigate('/page', {
formMethod: 'GET',
formData: new FormData(...),
});Each navigation (link click or form submission) in the Router is reflected via an internal state.navigation that indicates the state of the navigation. This concept of a navigation is a complex and heavily async bit of logic that is foundational to the Router's ability to manage data loading, submission, error handling, redirects, interruptions, and so on. Due to the user-driven nature of interruptions we don't quite believe it can be modeled as a finite state machine, however we have modeled some of the happy path flows below for clarity.
Note: This does not depict error or interruption flows.
graph LR
%% Link click
idle -->|link clicked| loading/normalLoad
subgraph "<Link> click"
loading/normalLoad -->|loader redirected| loading/normalRedirect
loading/normalRedirect --> loading/normalRedirect
end
loading/normalLoad -->|loaders completed| idle
loading/normalRedirect -->|loaders completed| idle
%% Form method=get
idle -->|form method=get| submitting/loaderSubmission
subgraph "<Form method=get>"
submitting/loaderSubmission -->|loader redirected| R1[loading/submissionRedirect]
R1[loading/submissionRedirect] --> R1[loading/submissionRedirect]
end
submitting/loaderSubmission -->|loaders completed| idle
R1[loading/submissionRedirect] -->|loaders completed| idle
%% Form method=post
idle -->|form method=post| submitting/actionSubmission
subgraph "<Form method=post>"
submitting/actionSubmission -->|action returned| loading/actionReload
submitting/actionSubmission -->|action redirected| R2[loading/submissionRedirect]
loading/actionReload -->|loader redirected| R2[loading/submissionRedirect]
R2[loading/submissionRedirect] --> R2[loading/submissionRedirect]
end
loading/actionReload -->|loaders completed| idle
R2[loading/submissionRedirect] -->|loaders completed| idle
idle -->|fetcher action redirect| R3[loading/submissionRedirect]
subgraph "Fetcher action redirect"
R3[loading/submissionRedirect] --> R3[loading/submissionRedirect]
end
R3[loading/submissionRedirect] -->|loaders completed| idle
Fetcher submissions and loads in the Router can each have their own internal states, indicated on fetcher.state and fetcher.type. As with navigations, these states are a complex and heavily async bit of logic that is foundational to the Router's ability to manage data loading, submission, error handling, redirects, interruptions, and so on. Due to the user-driven nature of interruptions we don't quite believe it can be modeled as a finite state machine, however we have modeled some of the happy path flows below for clarity.
Note: This does not depict error or interruption flows, nor the ability to re-use fetchers once they've reached idle/done.
graph LR
idle/init -->|"load"| loading/normalLoad
subgraph "Normal Fetch"
loading/normalLoad -.->|loader redirected| T1{{navigation}}
end
loading/normalLoad -->|loader completed| idle/done
T1{{navigation}} -.-> idle/done
idle/init -->|"submit (get)"| submitting/loaderSubmission
subgraph "Loader Submission"
submitting/loaderSubmission -.->|"loader redirected"| T2{{navigation}}
end
submitting/loaderSubmission -->|loader completed| idle/done
T2{{navigation}} -.-> idle/done
idle/init -->|"submit (post)"| submitting/actionSubmission
subgraph "Action Submission"
submitting/actionSubmission -->|action completed| loading/actionReload
submitting/actionSubmission -->|action redirected| loading/submissionRedirect
loading/submissionRedirect -.-> T3{{navigation}}
loading/actionReload -.-> |loaders redirected| T3{{navigation}}
end
T3{{navigation}} -.-> idle/done
loading/actionReload --> |loaders completed| idle/done
idle/done -->|"revalidate"| loading/revalidate
subgraph "Fetcher Revalidation"
loading/revalidate -.->|loader redirected| T4{{navigation}}
end
loading/revalidate -->|loader completed| idle/done
T4{{navigation}} -.-> idle/done
classDef navigation fill:lightgreen;
class T1,T2,T3,T4 navigation;