routes/

The identifier for the entry point when the application uses Conventional Routing.

Conventional routing uses routes/ as the convention for the entry point and analyzes the files in the src/routes directory to obtain the client-side routing configuration.

Any layout.[tj]sx and page.[tj]sx under src/routes will be used as the application's routes:

1.
2└── routes
3    ├── layout.tsx
4    ├── page.tsx
5    └── user
6        ├── layout.tsx
7        └── page.tsx

Basic Example

The directory name under routes will be used as the mapping of the route URL. layout.tsx is used as the layout component and page.tsx is used as the content component in the routing. They are the leaf nodes of the entire route. For example, the following directory structure:

.
└── routes
    ├── page.tsx
    └── user
        └── page.tsx

will generate two routes:

  • /
  • /user

Dynamic Routing

If the directory name of the route file is named with [], the generated route will be used as a dynamic route. For example, the following file directory:

└── routes ├── [id] │ └── page.tsx ├── blog │ └── page.tsx └── page.tsx

The routes/[id]/page.tsx file will be converted to the /:id route. Except for the /blog route that can be matched exactly, all other /xxx routes will be matched to this route.

In the component, you can use useParams to obtain the corresponding named parameter.

When using the loader function to obtain data, params will be passed as an input parameter to the loader function, and the corresponding parameter can be obtained through the attribute of params.

Layout Component

In the following example, a common layout component can be added to all route components by adding layout.tsx:

.
└── routes
    ├── layout.tsx
    ├── page.tsx
    └── user
        ├── layout.tsx
        └── page.tsx

In the layout component, you can use <Outlet> to represent the child components:

routes/layout.tsx
import { Link, Outlet, useLoaderData } from '@modern-js/runtime/router';

export default () => {
  return (
    <>
      <Outlet></Outlet>
    </>
  );
};
NOTE

<Outlet> is a new API in React Router 6. For details, see Outlet.

Upgrading to React Router v7

React Router v7 reduces bundle size (approximately 15% smaller) compared to React Router v6, provides a more efficient route matching algorithm, and offers better support for React 19 and TypeScript. There are very few breaking changes compared to React Router v6, and Modern.js has made both versions compatible, allowing for a seamless upgrade by simply installing and registering the appropriate plugin.

INFO

For more changes from React Router v6 to React Router v7, check the documentation

Requirements

React Router v7 has certain environment requirements:

  • Node.js 20+
  • React 18+
  • React DOM 18+

Install the Plugin

First, install the Modern.js React Router v7 plugin:

pnpm add @modern-js/plugin-router-v7

Configure the Plugin

Register the plugin in modern.config.ts:

modern.config.ts
import { routerPlugin } from '@modern-js/plugin-router-v7';

export default {
  runtime: {
    router: true,
  },
  plugins: [routerPlugin()],
};

Code Changes

In React Router v7, you no longer need to use the defer API; you can directly return data in the data loader:

routes/page.data.ts
import { defer } from '@modern-js/runtime/router';

export const loader = async ({ params }) => {
  // Recommended v7 style
  const user = fetchUser(params.id)
  return { user };

  // v6 style, still compatible with Modern.js
  return defer({ data: 'hello' });
};

React Router v7 has also deprecated the json API:

routes/page.data.ts
export const loader = async ({ params }) => {
  // Recommended v7 style
  return { data: 'hello' };

  // v6 style, still compatible with Modern.js
  return json({ data: 'hello' });
};