Resource
<Resource> components define the CRUD routes of a shadmin application.
Installation
pnpm dlx shadcn@latest add @shadmin/resourceA resource is a string that refers to an entity type (like ‘products’, ‘subscribers’, or ‘tags’). Records are objects with an id field, and two records of the same resource have the same field structure (e.g. all posts records have a title, a publication date, etc.).
A <Resource> component has 3 responsibilities:
- It defines the CRUD routes of a given resource (to display a list of records, the details of a record, or to create a new one).
- It creates a context that lets every descendant component know the current resource name (this context is called ResourceContext).
- It stores the resource definition (its name, icon, and label) inside a shared context (this context is called ResourceDefinitionContext).
Usage
<Resource> components can only be used as children of the <Admin> component.
For instance, the following admin app offers an interface to the resources exposed by the JSONPlaceholder API (posts, users, comments, and tags):
import {
Admin,
Resource,
ListGuesser,
EditGuesser,
ShowGuesser,
} from "@/components/admin";
import jsonServerProvider from "ra-data-json-server";
import { PostCreate, PostIcon } from "./posts";
import { CommentIcon } from "./comments";
const App = () => (
<Admin
dataProvider={jsonServerProvider("https://jsonplaceholder.typicode.com")}
>
{/* complete CRUD pages for posts */}
<Resource
name="posts"
group="Content"
list={ListGuesser}
edit={EditGuesser}
show={ShowGuesser}
create={PostCreate}
icon={PostIcon}
/>
{/* read-only user list */}
<Resource name="users" list={ListGuesser} />
{/* no show page for the comments resource */}
<Resource
name="comments"
group="Content"
list={ListGuesser}
edit={EditGuesser}
icon={CommentIcon}
/>
</Admin>
);The shadmin <Resource> wraps the headless ra-core resource component. It keeps the same routing behavior and adds the group prop used by the default sidebar menu.
The routes call the following dataProvider methods:
listcallsgetList()on mountshowcallsgetOne()on mounteditcallsgetOne()on mount, andupdate()ordelete()on submissioncreatecallscreate()on submission
Tip: Which API endpoint does a resource rely on? The <Resource> component doesn’t know this mapping - it’s the dataProvider’s job to define it.
Props
| Prop | Required | Type | Default | Description |
|---|---|---|---|---|
name | Required | string | - | The name of the resource, used to determine the API endpoint and the URL for the resource |
list | React.ComponentType | - | The component to render for the list view | |
create | React.ComponentType | - | The component to render for the create view | |
edit | React.ComponentType | - | The component to render for the edit view | |
show | React.ComponentType | - | The component to render for the show view | |
record Representation | string or function or React.ComponentType | - | The representation of a record to use in the UI | |
icon | React.ComponentType | - | The component to render in the menu | |
group | string | - | The group label used by the default sidebar menu | |
options | object | - | Additional options for the resource | |
children | Route | - | Sub-routes for the resource |
To learn more about these props, refer to the <Resource> component documentation on the ra-core website.
Lazy Loading
If you need to speed up the initial loading of your application, you may want to enable code splitting using React.lazy(). The default Shadmin layout uses Suspense, so there is no special setup required to use lazy loaded components in <Resource>.
// in src/App.js
import * as React from "react";
import { Admin, Resource } from "@/components/admin";
import { dataProvider } from "./data-provider";
const OrderList = React.lazy(() => import("./orders/order-list"));
const OrderEdit = React.lazy(() => import("./orders/order-edit"));
const App = () => (
<Admin dataProvider={dataProvider}>
<Resource name="orders" list={OrderList} edit={OrderEdit} />
...
</Admin>
);When users navigate to the /orders route, Shadmin will display the <Loading> component while the OrderList component is being loaded.
group
Use group to organize resources in the default <Menu>:
<Admin dataProvider={dataProvider}>
<Resource name="posts" group="Content" list={PostList} />
<Resource name="comments" group="Content" list={CommentList} />
<Resource name="orders" group="Store" list={OrderList} />
<Resource name="customers" list={CustomerList} />
</Admin>Resources with the same group render together under a sidebar label. Resources without group render last in an unlabeled section.