Skip to content

Commit 9d4149c

Browse files
committed
Start rewriting Architecture for headless
1 parent bc771f7 commit 9d4149c

File tree

1 file changed

+29
-51
lines changed

1 file changed

+29
-51
lines changed

docs_headless/src/content/docs/headless/guides/Architecture.md

Lines changed: 29 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -136,61 +136,34 @@ Whenever you need to communicate with a server, you will use these providers. Si
136136

137137
React-admin avoids components that accept an overwhelming number of props, which are often referred to as "God Components." Instead, react-admin encourages the use of composition, where components accept subcomponents (either through children or specific props) to handle a share of the logic.
138138

139-
For example, while you cannot directly pass a list of actions to the `<Edit>` component, you can achieve the same result by passing an `actions` component:
140-
141-
```jsx
142-
import { Button } from '@mui/material';
143-
import { TopToolbar, ShowButton } from 'react-admin';
144-
145-
export const PostEdit = () => (
146-
<Edit actions={<PostEditActions />}>
147-
...
148-
</Edit>
149-
);
150-
151-
const PostEditActions = () => (
152-
<TopToolbar>
153-
<ShowButton />
154-
<Button color="primary" onClick={customAction}>Custom Action</Button>
155-
</TopToolbar>
156-
);
157-
```
158-
159139
This approach enables you to override specific parts of the logic of a component by composing it with another component.
160140

161-
The trade-off with this approach is that sometimes react-admin may require you to override several components just to enable one specific feature. For instance, to override the Menu, you must first create a custom layout using your menu as the `<Layout menu>` prop, then pass it as the `<Admin layout>` prop:
141+
For instance, the `<CanAccess>` component accepts an `accessDenied` prop that allows you to define what to render when users don't have the required permissions:
162142

163143
```jsx
164-
// in src/MyLayout.js
165-
import { Layout } from 'react-admin';
166-
import { Menu } from './Menu';
167-
168-
export const MyLayout = ({ children }) => (
169-
<Layout menu={Menu}>
170-
{children}
171-
</Layout>
172-
);
173-
174-
// in src/App.js
175-
import { Admin } from 'react-admin';
176-
import { MyLayout } from './MyLayout';
177-
178-
const App = () => (
179-
<Admin layout={MyLayout} dataProvider={...}>
180-
// ...
181-
</Admin>
144+
import { CanAccess } from 'ra-core';
145+
import { PremiumStatsFeature } from './PremiumStatsFeature';
146+
import { UpgradeToPremium } from './UpgradeToPremium';
147+
148+
export const Dashboard = ({ children }) => (
149+
<div>
150+
<CanAccess accessDenied={<UpgradeToPremium />}>
151+
<PremiumStatsFeature />
152+
</CanAccess>
153+
</div>
182154
);
183155
```
184156

185-
Although this drawback exists, we accept it because the use of composition in react-admin makes the components highly extensible, and it significantly improves the readability and maintainability of the code.
186-
187157
## Hooks
188158

189-
When you find that you cannot tweak a react-admin component using props, you can always turn to the lower-level API: hooks. In fact, the core of react-admin is a headless library called `ra-core`, which primarily consists of hooks. These hooks hide the framework's implementation details, allowing you to focus on your business logic. It's perfectly normal to use react-admin hooks in your own components if the default UI doesn't meet your specific requirements.
159+
`ra-core` consists of hooks and headless components that hide the framework's implementation details, allowing you to focus on your business logic.
190160

191-
For example, the `<DeleteButton>` button used in `pessimistic` mode renders a confirmation dialog when clicked and then calls the `dataProvider.delete()` method for the current record. If you want the same feature but with a different UI, you can use the `useDeleteWithConfirmController` hook:
161+
For example, the `useDeleteWithConfirmController` button used in `pessimistic` mode renders a confirmation dialog when clicked and then calls the `dataProvider.delete()` method for the current record. If you want the same feature but with a different UI, you can use the `useDeleteWithConfirmController` hook:
192162

193163
```jsx
164+
import { useDeleteWithConfirmController, useRecordContext, useResourceContext } from 'ra-core';
165+
import { Button, Confirm } from 'my-awesome-ui-library';
166+
194167
const DeleteButton = () => {
195168
const resource = useResourceContext();
196169
const record = useRecordContext();
@@ -230,27 +203,32 @@ const DeleteButton = () => {
230203

231204
The fact that hook names often end with `Controller` is intentional and reflects the use of [the Model-View-Controller (MVC) pattern](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) for complex components in react-admin.
232205

233-
- The Controller logic is handled by React hooks (e.g. `useListController`).
234-
- The view logic is managed by React components (e.g. `<List>`).
206+
- The Controller logic is handled by React hooks (e.g. `useDeleteWithConfirmController`).
207+
- The view logic is managed by React components (e.g. `<DeleteButton>`).
235208
- The model logic is left to the developer, and react-admin simply defines the interface that the model must expose through its Providers.
236209

237-
React-admin exposes [dozens of hooks](./Reference.md#hooks) to assist you in building your own components. You can even construct an entire react-admin application without relying on the Material UI components and use a different UI kit if desired (see for instance [shadcn-admin-kit](https://github.com/marmelab/shadcn-admin-kit), a library for building admin apps with Shadcn UI). This flexibility allows you to tailor the application to your specific needs and preferences.
210+
React-admin exposes [dozens of hooks](./Reference.md#hooks) to assist you in building your own components. You can construct an entire react-admin application by using one of our UI packages such as `ra-ui-materialui` for Material UI components or [shadcn-admin-kit](https://github.com/marmelab/shadcn-admin-kit) for Shadcn UI or build your own UI layer. This flexibility allows you to tailor the application to your specific needs and preferences.
238211

239212
## Context: Pull, Don't Push
240213

241214
Communication between components can be challenging, especially in large React applications, where passing props down several levels can become cumbersome. React-admin addresses this issue using a pull model, where components expose props to their descendants via a context, and descendants can consume these props using custom hooks.
242215

243216
Whenever a react-admin component fetches data or defines a callback, it creates a context and places the data and callback in it.
244217

245-
For instance, the `<Admin>` component creates an `I18NProviderContext`, which exposes the `translate` function. All components in the application can utilize the `useTranslate` hook, which reads the `I18NProviderContext`, for translating labels and messages.
218+
For instance, the `<CoreAdminContext>` component creates an `I18NProviderContext`, which exposes the `translate` function. All components in the application can use the `useTranslate` hook or the `<Translate>` component, which reads the `I18NProviderContext`, for translating labels and messages.
246219

247220
```jsx
248-
import { useTranslate } from 'ra-core';
221+
import { Translate, useTranslate } from 'ra-core';
249222

250-
export const MyHelloButton = ({ handleClick }) => {
223+
export const MyHelloButton = () => {
251224
const translate = useTranslate();
225+
const handleClick = () => {
226+
alert(translate('root.button.hello_world.message'))
227+
}
252228
return (
253-
<button onClick={handleClick}>{translate('root.hello.world')}</button>
229+
<button onClick={handleClick}>
230+
<Translate i18nKey="root.button.hello_world.label">
231+
</button>
254232
);
255233
};
256234
```
@@ -301,4 +279,4 @@ React-admin provides the **best-in-class documentation**, demo apps, and support
301279

302280
That probably explains why more than 3,000 new apps are published every month using react-admin.
303281

304-
So react-admin is not just the assembly of [React Query](https://react-query.tanstack.com/), [react-hook-form](https://react-hook-form.com/), [react-router](https://reacttraining.com/react-router/), [Material UI](https://mui.com/material-ui/getting-started/), and [Emotion](https://github.com/emotion-js/emotion). It's a **framework** made to speed up and facilitate the development of single-page apps in React.
282+
So react-admin is not just the assembly of [React Query](https://react-query.tanstack.com/), [react-hook-form](https://react-hook-form.com/) and [react-router](https://reacttraining.com/react-router/). It's a **framework** made to speed up and facilitate the development of single-page apps in React.

0 commit comments

Comments
 (0)