Resource

<Resource> components define the CRUD routes of a shadmin application.

Installation

pnpm dlx shadcn@latest add @shadmin/resource

A 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:

  • list calls getList() on mount
  • show calls getOne() on mount
  • edit calls getOne() on mount, and update() or delete() on submission
  • create calls create() 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

PropRequiredTypeDefaultDescription
nameRequiredstring-The name of the resource, used to determine the API endpoint and the URL for the resource
listReact.ComponentType-The component to render for the list view
createReact.ComponentType-The component to render for the create view
editReact.ComponentType-The component to render for the edit view
showReact.ComponentType-The component to render for the show view
record Representationstring or function or React.ComponentType-The representation of a record to use in the UI
iconReact.ComponentType-The component to render in the menu
groupstring-The group label used by the default sidebar menu
optionsobject-Additional options for the resource
childrenRoute-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.