1. Project Overview & Quickstart (remix-run/react-router)
File: README.md
React Router is a multi-strategy router for React. You can use it maximally as a React framework or minimally as a library with your own architecture.
Packages
react-routercreate-react-router@react-router/dev@react-router/node@react-router/serve@react-router/express@react-router/architect@react-router/cloudflare@react-router/fs-routes
Previous Versions
File: docs/community/api-development-strategy.md
title: API Development Strategy
API Development Strategy
React Router is foundational to your application. We want to make sure that upgrading to new major versions is as smooth as possible while still allowing us to adjust and enhance the behavior and API as the React ecosystem advances.
Our strategy and motivations are discussed in more detail in our Future Flags blog post and our Open Governance Model.
Future Flags
When an API changes in a breaking way, it is introduced in a future flag. This allows you to opt-in to one change a time before it becomes the default in the next major version.
- Without enabling the future flag, nothing changes about your app
- Enabling the flag changes the behavior for that feature
All current future flags are documented in the Future Changes Guide to help you stay up-to-date.
Unstable Flags
Unstable flags are for features still being designed and developed and made available to our users to help us get it right.
Unstable flags are not recommended for production:
- they will change without warning and without upgrade paths
- they will have bugs
- they aren't documented
- they may be scrapped completely
When you opt-in to an unstable flag you are becoming a contributor to the project, rather than a user. We appreciate your help, but please be aware of the new role!
Because unstable flags are experimental and not guaranteed to stick around, we ship them in SemVer patch releases because they're not new stable/documented APIs. When an unstable flag stabilizes into a Future Flag, that will be released in a SemVer minor release and will be properly documented and added to the Future Changes Guide.
To learn about current unstable flags, keep an eye on the CHANGELOG.
Example New Feature Flow
The decision flow for a new feature looks something like this:
File: docs/community/contributing.md
title: Contributing
Contributing to React Router
Thanks for contributing, you rock!
When it comes to open source, there are many different kinds of contributions that can be made, all of which are valuable. Here are a few guidelines that should help you as you prepare your contribution.
Open Governance Model
Before going any further, please read the Open Governance blog post and document for information on how we handle bugs/issues/feature proposals in React Router.
Setup
Before you can contribute to the codebase, you will need to fork the repo. This will look a bit different depending on what type of contribution you are making:
- All new features, bug-fixes, documentation updates, or anything that touches
react-routercode should be branched off of and merged into themainbranch
The following steps will get you set up to contribute changes to this repo:
Fork the repo (click the Fork button at the top right of this page)
Clone your fork locally
bash# in a terminal, cd to parent directory where you want your clone to be, then git clone https://github.com/<your_github_username>/react-router.git cd react-routerInstall dependencies and build. React Router uses pnpm, so you should too. If you install using
npm, unnecessarypackage-lock.jsonfiles will be generated.
Think You Found a Bug?
Please conform to the issue template and provide a minimal and runnable reproduction. Best is a pull request with a failing test. Next best is a link to StackBlitz, CodeSandbox, or GitHub repository that illustrates the bug.
Issue Not Getting Attention?
If you need a bug fixed and nobody is fixing it, your best bet is to provide a fix for it and make a pull request. Open source code belongs to all of us, and it's all of our responsibility to push it forward.
Proposing New or Changed API?
โ ๏ธ Please do not start with a PR for a new feature.
New features need to go through the process outlined in the Open Governance Model and can be started by opening a Proposal Discussion on GitHub. Please provide thoughtful comments and some sample code that show what you'd like to do with React Router in your app. It helps the conversation if you can show us how you're limited by the current API first before jumping to a conclusion about what needs to be changed and/or added.
We have learned by experience that small APIs are usually better, so we may be a little reluctant to add something new unless there's an obvious limitation with the current API. That being said, we are always anxious to hear about cases that we just haven't considered before, so please don't be shy! :)
Adding an Example?
Examples can be added directly to the main branch. Create a branch off of your local clone of main. Once you've finished, create a pull request and outline your example.
Making a Pull Request?
Pull requests need only the approval of two or more collaborators to be merged; when the PR author is a collaborator, that counts as one.
main branch. You set the base in GitHub when authoring the PR with the dropdown below the "Compare changes" heading:
Tests
All commits that fix bugs or add features need one or more tests.
Change Files
In order to facilitate release notes generation, every PR with a user-facing impact should include one or more change files. You can generate these vis pnpm run changes:add (requires node 24+).
This tool will generate change files in the relevant packages//.changes/ directories. Change files are markdown files with a short description of the change. They should be named using the format <type>.<short-description>.md where type is either patch, minor, major, or unstable. For example:
patch.fix-fetcher-redirects.md
minor.add-some-new-api.md
major.require-node-24.md
unstable.update-unstable-api.mdCode of Conduct/Contributor License Agreement
All contributors must review the review the CLA and sign it by adding their github username to contributors.yml.
Docs + Examples
All commits that change or add to the API must be done in a pull request that also updates all relevant examples and docs.
Documentation is located in the docs directory. Once changes make their way into the main branch, they will automatically be published to the docs site.
If you want to preview how the changes will look on the docs site, clone the react-router-website repository and follow the instructions in README.md to view your changes locally.
Development
Packages
React Router uses a monorepo to host code for multiple packages. These packages live in the packages directory.
We use pnpm workspaces to manage installation of dependencies and running various scripts. To get everything installed, make sure you have pnpm installed, and then run pnpm install from the repo root.
Building
Calling pnpm build from the root directory will run the build, which should take only a few seconds. It's important to build all the packages together because the individual packages have dependencies on one another.
Testing
Before running the tests, you need to run a build. After you build, running pnpm test from the root directory will run every package's tests. If you want to run tests for a specific package, use pnpm test packages//:
# Test all packages
pnpm test
# Test only @react-router/dev
pnpm test packages/react-router-dev/Repository Branching
This repo maintains separate branches for different purposes. They will look something like this:
- main > the most recent release and current docs
- v6 > the most recent code for a specific major releaseThere may be other branches for various features and experimentation, but all of the magic happens from these branches.
Releases
Please refer to DEVELOPMENT.md for an outline of the release process.
File: docs/api/hooks/useActionData.md
title: useActionData
useActionData
[MODES: framework, data]
Summary
Returns the action data from
the most recent POST navigation form submission or undefined if there
hasn't been one.
import { Form, useActionData } from "react-router";
export async function action({ request }) {
const body = await request.formData();
const name = body.get("visitorsName");
return { message: `Hello, ${name}` };
}
export default function Invoices() {
const data = useActionData();
return (
<Form method="post">
{data ? data.message : "Waiting..."}
</Form>
);
}Signature
function useActionData<T = any>(): SerializeFrom<T> | undefinedReturns
The data returned from the route's action
function, or undefined if no action
has been called
File: docs/api/hooks/useAsyncError.md
title: useAsyncError
useAsyncError
[MODES: framework, data]
Summary
Returns the rejection value from the closest <Await>.
import { Await, useAsyncError } from "react-router";
function ErrorElement() {
const error = useAsyncError();
return (
Uh Oh, something went wrong! {error.message}
);
}
// somewhere in your app
<Await
resolve={promiseThatRejects}
errorElement={<ErrorElement />}
/>;Signature
function useAsyncError(): unknownReturns
The error that was thrown in the nearest Await component
File: docs/api/hooks/useAsyncValue.md
title: useAsyncValue
useAsyncValue
[MODES: framework, data]
Summary
Returns the resolved promise value from the closest <Await>.
function SomeDescendant() {
const value = useAsyncValue();
// ...
}
// somewhere in your app
<Await resolve={somePromise}>
<SomeDescendant />
</Await>;Signature
function useAsyncValue(): unknownReturns
The resolved value from the nearest Await component
File: docs/api/hooks/useBeforeUnload.md
title: useBeforeUnload
useBeforeUnload
[MODES: framework, data, declarative]
Summary
Set up a callback to be fired on Window's beforeunload event.
Signature
function useBeforeUnload(
callback: (event: BeforeUnloadEvent) => any,
options?: {
capture?: boolean;
},
): voidParams
callback
The callback to be called when the beforeunload event is fired.
options.capture
If true, the event will be captured during the capture phase. Defaults to false.
Returns
No return value.
2. Official Technical Reference & Guides (remix-run/react-router-website)
File: README.md
React Router Website!
Contributing
If you want to make a contribution
- Fork and clone this repo
- Create a branch
- Push any changes you make to your branch
- Open up a PR in this Repo
Setup
First setup your .env file, use .env.example to know what to set.
cp .env.example .envInstall dependencies
pnpm installLocal Development
Now you should be good to go:
pnpm run devTo preview local changes to the docs folder in the React Router repo, select "local" from the version dropdown menu on the site. Make sure you have the react-router repo cloned locally and LOCAL_REPO_RELATIVE_PATH is pointed to the correct filepath.
We leverage a number of LRUCache's to server-side cache various resources, such as processed markdown from GitHub, that expire at various times (usually after 5 minutes). If you want them to expire immediately for local development, set the NO_CACHE environment variable.
NO_CACHE=1 pnpm run devNote that by default this assumes the relative path to your local copy of the React Router docs is ../react-router. This can be configured via LOCAL_REPO_RELATIVE_PATH in your .env file.
Preview
To preview the production build locally:
pnpm run build
pnpm run previewDeployment
The production server is always in sync with main
git push origin main
open https://reactrouter.comPushing the "stage" tag will deploy to staging.
git checkout my/branch
# moves the `stage` tag and pushes it, triggering a deploy
pnpm run push:stageWhen you're happy with it, merge your branch into main and push.
CSS Notes
You'll want the tailwind VSCode plugin for sure, the hints are amazing.
The color scheme has various shades but we also have a special "brand" rule for each of our brand colors so we don't have to know the specific number of that color like this: ``.
We want to use Tailwind's default classes as much as possible to avoid a large CSS file. A few things you can do to keep the styles shared:
- Avoid changing anything but the theme in
tailwind.config.js, no special classes, etc. - Avoid "inline rules" like
color-[#ccc]as much as possible. - Silly HTML (like a wrapper div to add padding on a container) is better than one-off css rules.
Algolia Search
We use DocSearch by Algolia for our documentation's search. The site is automatically scraped and indexed weekly by the Algolia Crawler.
If the doc search results ever seem outdated or incorrect be sure to check that the crawler isn't blocked. If it is, it might just need to be canceled and restarted to kick things off again. There is also an editor in the Crawler admin that lets you adjust the crawler's script if needed.
File: app/components/_playground/README.md
Visit http://localhost:3000/__components to render the playground.
It's like bootleg storybook so you can build/tweak/play around with components in isolation
File: app/modules/README.md
This folder is for modules that could potentially be published to npm
- could be used in any Remix app
- no clue about this actual app
- no dependency on styling/tailwind etc.
- ideally has some tests
NOTE: please put them in their own folder (like they would be if the were in node_modules/[the thing]).
File: app/ui/README.md
I don't know what this folder is for, should probably get everything out of here