diff --git a/docs/Resource.md b/docs/Resource.md index 418dcea7647..985acf971ca 100644 --- a/docs/Resource.md +++ b/docs/Resource.md @@ -5,33 +5,21 @@ title: "The Resource Component" # The `` component -A `` component maps one API endpoint to a CRUD interface. For instance, the following admin app offers a read-only interface to the resources exposed by the JSONPlaceholder API at [https://jsonplaceholder.typicode.com/posts](https://jsonplaceholder.typicode.com/posts) and [https://jsonplaceholder.typicode.com/users](https://jsonplaceholder.typicode.com/users): +`` components are fundamental building blocks in react-admin apps. They form the skeleton of the application, and of its internal data store. -```jsx -// in src/App.js -import * as React from "react"; -import { Admin, Resource } from 'react-admin'; -import jsonServerProvider from 'ra-data-json-server'; +In react-admin terms, 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). -import { PostList } from './posts'; -import { UserList } from './users'; +A `` component has 3 responsibilities: -const App = () => ( - - - - -); -``` +- It defines the page components to use for interacting with the resource records (to display a list of records, the details of a record, or to create a new one). +- It initializes the internal data store so that react-admin components can see it as a mirror of the API for a given resource. +- It creates a context that lets every descendent component know in which resource they are used (this context is called `ResourceContext`). -`` allows you to define a component for each CRUD operation, using the following prop names: +`` components can only be used as children of [the `` component](./Admin.md). -* `list` (if defined, the resource is displayed on the Menu) -* `create` -* `edit` -* `show` +## Basic Usage -Here is a more complete admin, with components for all the CRUD operations: +For instance, the following admin app offers an interface to the resources exposed by the JSONPlaceholder API ([posts](https://jsonplaceholder.typicode.com/posts), [users](https://jsonplaceholder.typicode.com/users), [comments](https://jsonplaceholder.typicode.com/comments), and [tags](https://jsonplaceholder.typicode.com/tags)): ```jsx import * as React from "react"; @@ -44,32 +32,25 @@ import { CommentList, CommentEdit, CommentCreate, CommentIcon } from './comments const App = () => ( - + {/* complete CRUD pages for posts */} + + {/* read-only user list */} + {/* no show page for the comments resource */} + {/* no standalone page for tags, but the resource is required to display tags in posts */} ); ``` -**Tip**: Under the hood, the `` component uses [react-router](https://reactrouter.com/web/guides/quick-start) to create several routes: - -* `/` maps to the `list` component -* `/create` maps to the `create` component -* `/:id` maps to the `edit` component -* `/:id/show` maps to the `show` component - -**Tip**: You must add a `` when you declare a reference (via ``, ``, ``, `` or ``), because react-admin uses resources to define the data store structure. That's why there is an empty `tag` resource in the example above. +**Tip**: You must add a `` when you declare a reference (via ``, ``, ``, `` or ``), because react-admin uses resources to define the data store structure. That's why there is an empty `tags` resource in the example above. -`` also accepts additional props: - -* [`name`](#name) -* [`icon`](#icon) -* [`options`](#icon) +**Tip**: How does a resource map to an API endpoint? The `` component doesn't know this mapping - it's [the `dataProvider`'s job](./DataProviders.md) to define it. ## `name` -React-admin uses the `name` prop both to determine the API endpoint (passed to the `dataProvider`), and to form the URL for the resource. +`name` is the only required prop for a ``. React-admin uses the `name` prop both to determine the API endpoint (passed to the `dataProvider`), and to form the URL for the resource. ```jsx @@ -84,7 +65,29 @@ The routing will map the component as follows: * `/posts/:id` maps to `PostEdit` * `/posts/:id/show` maps to `PostShow` -**Tip**: If you want to use a special API endpoint (e.g. 'https://jsonplaceholder.typicode.com/my-custom-posts-endpoint') without altering the URL in the react-admin application (so still use `/posts`), write the mapping from the resource `name` (`posts`) to the API endpoint (`my-custom-posts-endpoint`) in your own [`dataProvider`](./Admin.md#dataprovider) +**Tip**: If you want to use a special API endpoint (e.g. 'https://jsonplaceholder.typicode.com/my-custom-posts-endpoint') without altering the URL in the react-admin application (so still use `/posts`), write the mapping from the resource `name` (`posts`) to the API endpoint (`my-custom-posts-endpoint`) in your own [`dataProvider`](./Admin.md#dataprovider). + +## CRUD Props + +`` allows you to define a component for each CRUD operation, using the following prop names: + +* `list` (if defined, the resource is displayed on the Menu) +* `create` +* `edit` +* `show` + +**Tip**: Under the hood, the `` component uses [react-router](https://reactrouter.com/web/guides/quick-start) to create several routes: + +* `/` maps to the `list` component +* `/create` maps to the `create` component +* `/:id` maps to the `edit` component +* `/:id/show` maps to the `show` component + +`` also accepts additional props: + +* [`name`](#name) +* [`icon`](#icon) +* [`options`](#icon) ## `icon` @@ -117,3 +120,42 @@ const App = () => ( ``` {% endraw %} + +## Resource Context + +`` also creates a `RecordContext`, that gives access to the current resource name to all descendents of the main page components (`list`, `create`, `edit`, `show`). + +to read the current resource name, use the `useResourceContext()` hook. + +For instance, the following component displays the name of the current resource: + +```jsx +const ResourceName = () => { + const { resource } = useResourceContext(); + return <>{resource}; +} + +const PostList = (props) => ( + + <> + {/* renders 'posts' */} + + + + + <> + +) +``` + +**Tip**: You can *change* the current resource context, e.g. to use a component designed for a related resource inside another entity. Use the `` component for that: + +```jsx +const MyComponent = () => ( + + {/* renders 'comments' */} + ... + +); +``` +