Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document dynamic resources #5004

Merged
merged 6 commits into from
Jul 6, 2020
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 47 additions & 6 deletions docs/Admin.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ Here are all the props accepted by the component:

- [The `<Admin>` Component](#the-admin-component)
- [`dataProvider`](#dataprovider)
- [`authProvider`](#authprovider)
fzaninotto marked this conversation as resolved.
Show resolved Hide resolved
- [`i18nProvider`](#internationalization)
fzaninotto marked this conversation as resolved.
Show resolved Hide resolved
- [`title`](#title)
- [`dashboard`](#dashboard)
- [`catchAll`](#catchall)
Expand All @@ -40,12 +38,15 @@ Here are all the props accepted by the component:
- [`customReducers`](#customreducers)
- [`customSagas`](#customsagas)
- [`customRoutes`](#customroutes)
- [`authProvider`](#authprovider)
- [`loginPage`](#loginpage)
- [`logoutButton`](#logoutbutton)
- [`initialState`](#initialstate)
- [`history`](#history)
- [Internationalization](#internationalization)
- [Declaring resources at runtime](#declaring-resources-at-runtime)
- [Use a Function As its Child](#use-a-function-as-its-child)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should link to level 3 headers in this list

- [Unplug the <Admin> using the `<AdminContext>` and the `<AdminUI>`](#unplug-the-admin-using-the-admincontext-and-the-adminui)
- [Using react-admin without `<Admin>` and `<Resource>`](#using-react-admin-without-admin-and-resource)

## `dataProvider`
Expand Down Expand Up @@ -442,7 +443,7 @@ const Foo = () => (
export default Foo;
```

**Tip**: Custom routes can be [a `<Redirect>` route](https://reacttraining.com/react-router/web/api/Redirect), too.
**Tip**: Custom routes can be [a `<Redirect>` route](https://reacttraining.com/react-router/web/api/Redirect), too.

## `authProvider`

Expand Down Expand Up @@ -533,7 +534,6 @@ const App = () => (
);
```


## `history`

By default, react-admin creates URLs using a hash sign (e.g. "myadmin.acme.com/#/posts/123"). The hash portion of the URL (i.e. `#/posts/123` in the example) contains the main application route. This strategy has the benefit of working without a server, and with legacy web browsers. But you may want to use another routing strategy, e.g. to allow server-side rendering.
Expand All @@ -559,13 +559,16 @@ The `i18nProvider` props let you translate the GUI. The [Translation Documentati

## Declaring resources at runtime

You might want to dynamically define the resources when the app starts. The `<Admin>` component accepts a function as its child and this function can return a Promise. If you also defined an `authProvider`, the child function will receive the result of a call to `authProvider.getPermissions()` (you can read more about this in the [Authorization](./Authorization.md) chapter).
You might want to dynamically define the resources when the app starts.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sentence alone with the section title afterwards feels odd.


### Use a Function As its Child
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### Use a Function As its Child
### Using a Function As `<Admin>` Child


The `<Admin>` component accepts a function as its child and this function can return a Promise. If you also defined an `authProvider`, the child function will receive the result of a call to `authProvider.getPermissions()` (you can read more about this in the [Authorization](./Authorization.md) chapter).

For instance, getting the resource from an API might look like:

```jsx
import * as React from "react";

import { Admin, Resource } from 'react-admin';
import simpleRestProvider from 'ra-data-simple-rest';

Expand Down Expand Up @@ -595,6 +598,44 @@ const App = () => (
);
```

### Unplug the <Admin> using the `<AdminContext>` and the `<AdminUI>`

Setting Resources dynamically is still very cumbersome: even if `<Admin>` accepts [a function as child](#declaring-resources-at-runtime), this function can't execute hooks.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Setting Resources dynamically is still very cumbersome: even if `<Admin>` accepts [a function as child](#declaring-resources-at-runtime), this function can't execute hooks.
Setting Resources dynamically using the children-as-function syntax may not be enough in all cases, because this function can't execute hooks.


So it's impossible, for instance, to have a dynamic list of resources based on a call to the dataProvider (since the dataProvider is only defined after the Admin component renders).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
So it's impossible, for instance, to have a dynamic list of resources based on a call to the dataProvider (since the dataProvider is only defined after the Admin component renders).
So it's impossible, for instance, to have a dynamic list of resources based on a call to the `dataProvider` (since the `dataProvider` is only defined after the `<Admin>` component renders).


To do so, you have to build your own <Admin> component using both the <AdminContext> and the <AdminUI> (as we do internally). It's straightforward.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add backticks around components

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
To do so, you have to build your own <Admin> component using both the <AdminContext> and the <AdminUI> (as we do internally). It's straightforward.
To overcome this limitation, you can build your own `<Admin>` component using two lower-level components: `<AdminContext>` (responsible for putting the providers in contexts) and `<AdminUI>` (responsible for displaying the UI). Here is an example:


``` jsx
import * as React, { useEffect, useState } from 'react';
import { AdminContext, AdminUI, Resource, ListGuesser, useDataProvider } from 'react-admin';

function App() {
return (
<AdminContext dataProvider={myDataProvider}>
<AsyncResources />
</AdminContext>
);
}

function AsyncResources() {
const [resources, setResources] = useState([]);
const dataProvider = useDataProvider();

useEffect(() => {
dataProvider.introspect().then(r => setResources(r));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

introspect isn't a legal dataProvider verb, so you'll have to be more explicit here

}, []);

return (
<AdminUI>
{resources.map(resource => (
<Resource name={resource.name} key={resource.key} list={ListGuesser} />
))}
</AdminUI>
);
}
```

## Using react-admin without `<Admin>` and `<Resource>`

Using `<Admin>` and `<Resource>` is completely optional. If you feel like bootstrapping a redux app yourself, it's totally possible. Head to [Including in another app](./CustomApp.md) for a detailed how-to.