useDefineAppLocation
This Enterprise Edition hook lets you define the app location for a page, used by components like <Breadcrumb>
and <IconMenu>
to render the current location.
In the following example, the <SongEditForArtist>
component is a nested resource rendering at the /artists/:id/songs/:songId
path. It uses useDefineAppLocation
to define the app location as artists.edit.songs.edit
, and passes the record
and song
objects as parameters to let the breadcrumb component render the record and song names.
import { useParams } from 'react-router-dom';
import { Edit, SimpleForm, TextInput, DateInput, useGetOne } from 'react-admin';
import { useDefineAppLocation } from '@react-admin/ra-navigation';
const SongEditForArtist = () => {
const { id, songId } = useParams<{ id: string; songId: string }>();
const { data: record } = useGetOne('artists', { id });
const { data: song } = useGetOne('songs', { id: songId });
useDefineAppLocation('artists.edit.songs.edit', { record, song });
return (
<Edit resource="songs" id={songId} redirect={`/artists/${id}/songs`}>
<SimpleForm>
<TextInput source="title" />
<DateInput source="released" />
<TextInput source="writer" />
<TextInput source="producer" />
<TextInput source="recordCompany" label="Label" />
</SimpleForm>
</Edit>
);
};
Tip: The <Edit>
component will call dataProvider.getOne("songs", { id: songId })
to fetch the song record. Since the <SongEditForArtist>
component makes the same request, React-admin will deduplicate the calls and only make one request to the dataProvider.
Tip: If you don’t call useDefineAppLocation
anywhere on a page, the AppLocationContext will deduce a resource app location from the current URL path (e.g. artists.edit
for the /artists/:id
path).
Here is how a custom Breadcrumb would use location values
to render the record and song names:
const MyBreadcrumb = () => (
<Breadcrumb>
<Breadcrumb.Item name="artists" label="Artists" to="/artists">
<Breadcrumb.Item
name="edit"
label={({ record }: { record?: Artist }) => record?.name}
to={({ record }: { record?: Artist }) =>
`/artists/${record?.id}`
}
>
<Breadcrumb.Item
name="songs"
label="Songs"
to={({ record }: { record?: Artist }) =>
`/artists/${record?.id}/songs`
}
>
<Breadcrumb.Item
name="edit"
label={({ song }: { song?: Song }) => song?.title}
to={({ song }: { song?: Song }) =>
`/artists/${song?.artist_id}/songs/${song?.id}`
}
/>
</Breadcrumb.Item>
</Breadcrumb.Item>
<Breadcrumb.Item
name="create"
label="Create"
to="/artists/create"
/>
</Breadcrumb.Item>
</Breadcrumb>
);
Usage
This component requires that the application layout is wrapped with <AppLocationContext>
(which is already the case for <ContainerLayout>
and <SolarLayout>
):
// in src/MyLayout.jsx
import { AppLocationContext, Breadcrumb } from '@react-admin/ra-navigation';
import { Layout } from 'react-admin';
import { MyBreadcrumb } from './MyBreadcrumb';
export const MyLayout = ({ children, ...rest }) => (
<AppLocationContext>
<Layout {...rest}>
<MyBreadcrumb />
{children}
</Layout>
</AppLocationContext>
);
Then, a page component can define its app location by passing a string composed of location segments separated by a dot to the useDefineAppLocation
hook:
// in src/UserPreferences.jsx
import { useDefineAppLocation } from '@react-admin/ra-navigation';
const UserPreferences = () => {
useDefineAppLocation('user.preferences');
return <span>My Preferences</span>;
};
Let’s say that this custom page is added to the app under the /preferences
URL:
// in src/App.jsx
import { Admin, Resource, CustomRoutes, } from 'react-admin';
import { Route } from 'react-router-dom';
import { MyLayout } from './MyLayout';
import { UserPreferences } from './UserPreferences';
const App = () => (
<Admin dataProvider={dataProvider} layout={MyLayout}>
...
<CustomRoutes>
<Route exact path="/preferences" component={UserPreferences} />,
</CustomRoutes>
</Admin>
);
Components inside the app, like <Breadcrumb>
, can read the current app location and define custom items for the 'user.preferences'
location.
// in src/MyBreadcrumb.jsx
import { Breadcrumb } from '@react-admin/ra-navigation';
export const MyBreadcrumb = () => (
<Breadcrumb>
<Breadcrumb.ResourceItems />
<Breadcrumb.Item name="user" label="User">
<Breadcrumb.Item name="preferences" label="Preferences" to="/preferences" />
</Breadcrumb.Item>
</Breadcrumb>
);
App Location For CRUD Pages
You don’t need to define the app location for CRUD pages as react-admin does it by default:
- List:
[resource].list
- Create:
[resource].create
- Edit:
[resource].edit
. The location also contains the currentrecord
- Show:
[resource].show
. The location also contains the currentrecord
However, you can customize these default app locations in your CRUD pages. For instance, to create a Post List page with the app location set to posts.published
, you can do the following:
import { List, Datagrid, TextField } from 'react-admin';
import { useDefineAppLocation } from '@react-admin/ra-navigation';
export const PublishedPostsList = () => {
useDefineAppLocation('posts.published');
return (
<List filter={{ isPublished: true }}>
<Datagrid>
<TextField source="title" />
...
</Datagrid>
</List>
);
}
Dependent Components
The following components read the app location context: