Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Doc] Update Admin and Routing docs to encourage using a Data Router #10220

Merged
merged 5 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 51 additions & 28 deletions docs/Admin.md
Original file line number Diff line number Diff line change
Expand Up @@ -1035,44 +1035,59 @@ const App = () => (
export default App;
```

## Using A Custom Router
## Using A Custom Router

React-admin uses [the react-router library](https://reactrouter.com/) to handle routing, with a [HashRouter](https://reactrouter.com/en/6/router-components/hash-router#hashrouter). This means that the hash portion of the URL (i.e. `#/posts/123` in the example) contains the main application route. This strategy has the benefit of working without a server, and with legacy web browsers.

But you may want to use another routing strategy, e.g. to allow server-side rendering of individual pages. React-router offers various Router components to implement such routing strategies. If you want to use a different router, simply wrap it around your app. React-admin will detect that it's already inside a router, and skip its own router.
But you may want to use another routing strategy, e.g. to allow server-side rendering of individual pages. React-router offers various Router components to implement such routing strategies. If you want to use a different router, simply put your app in a create router function. React-admin will detect that it's already inside a router, and skip its own router.

```tsx
import { BrowserRouter } from 'react-router-dom';
import { RouterProvider, createBrowserRouter } from 'react-router-dom';
import { Admin, Resource } from 'react-admin';
import { dataProvider } from './dataProvider';

const App = () => (
<BrowserRouter>
<Admin dataProvider={dataProvider}>
<Resource name="posts" />
</Admin>
</BrowserRouter>
);
const App = () => {
const router = createBrowserRouter([
{
path: "*",
element: (
<Admin dataProvider={dataProvider}>
<Resource name="posts" />
</Admin>
),
},
]);
return <RouterProvider router={router} />;
};
```

## Using React-Admin In A Sub Path

React-admin links are absolute (e.g. `/posts/123/show`). If you serve your admin from a sub path (e.g. `/admin`), react-admin works seamlessly as it only appends a hash (URLs will look like `/admin#/posts/123/show`).

However, if you serve your admin from a sub path AND use another Router (like [`<BrowserRouter>`](https://reactrouter.com/en/main/router-components/browser-router) for instance), you need to set the `<Admin basename>` prop, so that react-admin routes include the basename in all links (e.g. `/admin/posts/123/show`).
However, if you serve your admin from a sub path AND use another Router (like [`createBrowserRouter`](https://reactrouter.com/en/main/routers/create-browser-router) for instance), you need to set the [`opts.basename`](https://reactrouter.com/en/main/routers/create-browser-router#optsbasename) of `createBrowserRouter` function, so that react-admin routes include the basename in all links (e.g. `/admin/posts/123/show`).

```tsx
import { Admin, Resource } from 'react-admin';
import { BrowserRouter } from 'react-router-dom';
import { RouterProvider, createBrowserRouter } from 'react-router-dom';
import { dataProvider } from './dataProvider';

const App = () => (
<BrowserRouter>
<Admin basename="/admin" dataProvider={dataProvider}>
<Resource name="posts" />
</Admin>
</BrowserRouter>
);
const App = () => {
const router = createBrowserRouter(
[
{
path: "*",
element: (
<Admin dataProvider={dataProvider}>
<Resource name="posts" />
</Admin>
),
},
],
{ basename: "/admin" },
);
return <RouterProvider router={router} />;
};
```

This makes all links be prefixed with `/admin`.
Expand All @@ -1086,18 +1101,26 @@ If you want to use react-admin as a sub path of a larger React application, chec
You can include a react-admin app inside another app, using a react-router `<Route>`:

```tsx
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { RouterProvider, Routes, Route, createBrowserRouter } from 'react-router-dom';
import { StoreFront } from './StoreFront';
import { StoreAdmin } from './StoreAdmin';

export const App = () => (
<BrowserRouter>
<Routes>
<Route path="/" element={<StoreFront />} />
<Route path="/admin/*" element={<StoreAdmin />} />
</Routes>
</BrowserRouter>
);
export const App = () => {
const router = createBrowserRouter(
[
{
path: "*",
element: (
<Routes>
<Route path="/" element={<StoreFront />} />
<Route path="/admin/*" element={<StoreAdmin />} />
</Routes>
),
},
],
);
return <RouterProvider router={router} />;
};
```

React-admin will have to prefix all the internal links with `/admin`. Use the `<Admin basename>` prop for that:
Expand Down
98 changes: 63 additions & 35 deletions docs/Routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,74 +125,102 @@ export default App;

## Using A Custom Router

By default, react-admin creates a [HashRouter](https://reactrouter.com/en/6/router-components/hash-router#hashrouter). The hash portion of the URL (i.e. `#/posts/123` in the example) contains the main application route. This strategy has the benefit of working without a server, and with legacy web browsers.
React-admin uses [the react-router library](https://reactrouter.com/) to handle routing, with a [HashRouter](https://reactrouter.com/en/routers/create-hash-router). This means that the hash portion of the URL (i.e. `#/posts/123` in the example) contains the main application route. This strategy has the benefit of working without a server, and with legacy web browsers.

But you may want to use another routing strategy, e.g. to allow server-side rendering. React-router offers various Router components to implement such routing strategies. If you want to use a different router, simply wrap it around your app. React-admin will detect that it's already inside a router, and skip its own router.
But you may want to use another routing strategy, e.g. to allow server-side rendering of individual pages. React-router offers various Router components to implement such routing strategies. If you want to use a different router, simply put your app in a create router function. React-admin will detect that it's already inside a router, and skip its own router.

```jsx
import { BrowserRouter } from 'react-router-dom';
```tsx
import { RouterProvider, createBrowserRouter } from 'react-router-dom';
import { Admin, Resource } from 'react-admin';

const App = () => (
<BrowserRouter>
<Admin dataProvider={...}>
<Resource name="posts" />
</Admin>
</BrowserRouter>
);
import { dataProvider } from './dataProvider';

const App = () => {
const router = createBrowserRouter([
{
path: "*",
element: (
<Admin dataProvider={dataProvider}>
<Resource name="posts" />
</Admin>
),
},
]);
return <RouterProvider router={router} />;
};
```

## Using React-Admin In A Sub Path

React-admin links are absolute (e.g. `/posts/123/show`). If you serve your admin from a sub path (e.g. `/admin`), react-admin works seamlessly as it only appends a hash (URLs will look like `/admin#/posts/123/show`).

However, if you serve your admin from a sub path AND use another Router (like `BrowserRouter` for instance), you need to set the `<BrowserRouter basename>` prop, so that react-admin routes include the basename in all links (e.g. `/admin/posts/123/show`).
However, if you serve your admin from a sub path AND use another Router (like [`createBrowserRouter`](https://reactrouter.com/en/main/routers/create-browser-router) for instance), you need to set the [`opts.basename`](https://reactrouter.com/en/main/routers/create-browser-router#optsbasename) of `createBrowserRouter` function, so that react-admin routes include the basename in all links (e.g. `/admin/posts/123/show`).

```jsx
```tsx
import { Admin, Resource } from 'react-admin';

const App = () => (
<BrowserRouter basename="/admin">
<Admin dataProvider={...}>
<Resource name="posts" />
</Admin>
</BrowserRouter>
);
import { RouterProvider, createBrowserRouter } from 'react-router-dom';
import { dataProvider } from './dataProvider';

const App = () => {
const router = createBrowserRouter(
[
{
path: "*",
element: (
<Admin dataProvider={dataProvider}>
<Resource name="posts" />
</Admin>
),
},
],
{ basename: "/admin" },
);
return <RouterProvider router={router} />;
};
```

This makes all links be prefixed with `/admin`.

Note that it is your responsibility to serve the admin from the sub path, e.g. by setting the `homepage` field in your `package.json` if you use [Create React App](https://create-react-app.dev/docs/deployment/#building-for-relative-paths).
Note that it is your responsibility to serve the admin from the sub path, e.g. by setting the `base` field in `vite.config.ts` if you use [Vite.js](https://vitejs.dev/config/shared-options.html#base), or the `homepage` field in `package.json` if you use [Create React App](https://create-react-app.dev/docs/deployment/#building-for-relative-paths).

If you want to use react-admin as a sub path of a larger React application, check the next section for instructions.

## Using React-Admin Inside a Route

You can include a react-admin app inside another app, using a react-router `<Route>`:

```jsx
import { BrowserRouter, Routes, Route } from 'react-router-dom';
```tsx
import { RouterProvider, Routes, Route, createBrowserRouter } from 'react-router-dom';
import { StoreFront } from './StoreFront';
import { StoreAdmin } from './StoreAdmin';

export const App = () => (
<BrowserRouter>
<Routes>
<Route path="/" element={<StoreFront />} />
<Route path="/admin/*" element={<StoreAdmin />} />
</Routes>
</BrowserRouter>
);
export const App = () => {
const router = createBrowserRouter(
[
{
path: "*",
element: (
<Routes>
<Route path="/" element={<StoreFront />} />
<Route path="/admin/*" element={<StoreAdmin />} />
</Routes>
),
},
],
);
return <RouterProvider router={router} />;
};
```

React-admin will have to prefix all the internal links with `/admin`. Use the `<Admin basename>` prop for that:

```jsx
```tsx
// in src/StoreAdmin.js
import { Admin, Resource } from 'react-admin';
import { dataProvider } from './dataProvider';
import posts from './posts';

export const StoreAdmin = () => (
<Admin basename="/admin" dataProvider={...}>
<Admin basename="/admin" dataProvider={dataProvider}>
<Resource name="posts" {...posts} />
</Admin>
);
Expand Down