diff --git a/docs/Actions.md b/docs/Actions.md index 3b6ac45b2f3..c38d47ea87c 100644 --- a/docs/Actions.md +++ b/docs/Actions.md @@ -620,10 +620,152 @@ const ApproveButton = ({ record }) => { Fetching data is called a *side effect*, since it calls the outside world, and is asynchronous. Usual actions may have other side effects, like showing a notification, or redirecting the user to another page. React-admin provides the following hooks to handle most common side effects: -- `useNotify`: Return a function to display a notification. The arguments should be a message (it can be a translation key), a level (either `info`, `success` or `warning`), an `options` object to pass to the `translate` function (in the case of the default i18n provider, using Polyglot.js, it will be the interpolation options used for passing variables), a boolean to set to `true` if the notification should contain an "undo" button and a number corresponding to the notification duration. -- `useRedirect`: Return a function to redirect the user to another page. The arguments should be the path to redirect the user to, and the current `basePath`. -- `useRefresh`: Return a function to force a rerender of the current view (equivalent to pressing the Refresh button). -- `useUnselectAll`: Return a function to unselect all lines in the current `Datagrid`. Pass the name of the resource as argument. +- [`useNotify`](#usenotify): Return a function to display a notification. +- [`useRedirect`](#useredirect): Return a function to redirect the user to another page. +- [`useRefresh`](#userefresh): Return a function to force a rerender of the current view (equivalent to pressing the Refresh button). +- [`useUnselectAll`](#useunselectall): Return a function to unselect all lines in the current `Datagrid`. + +### `useNotify` + +This hook returns a function that displays a notification in the bottom of the page. + +```jsx +import { useNotify } from 'react-admin'; + +const NotifyButton = () => { + const notify = useNotify(); + const handleClick = () => { + notify(`Comment approved`, 'success'); + } + return ; +}; +``` + +The callback takes 5 arguments: + - the message to display + - the level of the notification (`info`, `success` or `warning` - the default is `info`) + - an `options` object to pass to the `translate` function (because notificatoin messages are translated if your admin has an `i18nProvider`). It is useful for inserting variables into the translation. + - an `undoable` boolean. Set it to `true` if the notification should contain an "undo" button + - a `duration` number. Set it to `0` if the notification should not be dismissable. + +Here are more examples of `useNotify` calls: + +```jsx +// notify a warning +notify(`This is a warning`, 'warning'); +// pass translation arguments +notify('item.created', 'info', { resource: 'post' }); +// send an undoable notification +notify('Element updated', 'info', undefined, true); +``` + +**Tip**: When using `useNotify` as a side effect for an `undoable` Edit form, you MUST set the fourth argument to `true`, otherwise the "undo" button will not appear, and the actual update will never occur. + +```jsx +import * as React from 'react'; +import { useNotify, Edit, SimpleForm } from 'react-admin'; + +const PostEdit = props => { + const notify = useNotify(); + + const onSuccess = () => { + notify(`Changes saved`, undefined, undefined, true); + }; + + return ( + + + ... + + + ); +} +``` + +### `useRedirect` + +This hook returns a function that redirects the user to another page. + +```jsx +import { useRedirect } from 'react-admin'; + +const DashboardButton = () => { + const redirect = useRedirect(); + const handleClick = () => { + redirect('/dashboard'); + } + return ; +}; +``` + +The callback takes 3 arguments: + - the page to redirect the user to ('list', 'create', 'edit', 'show', or a custom path) + - the current `basePath` + - the `id` of the record to redirect to (if any) + +Here are more examples of `useRedirect` calls: + +```jsx +// redirect to the post list page +redirect('list', '/posts'); +// redirect to the edit page of a post: +redirect('edit', '/posts', 1); +// redirect to the post creation page: +redirect('create', '/posts'); +``` + +Note that `useRedirect` doesn't allow to redirect to pages outside the current React app. For that, you should use `document.location`. + +### `useRefresh` + +This hook returns a function that forces a rerender of the current view. + +```jsx +import { useRefresh } from 'react-admin'; + +const RefreshButton = () => { + const refresh = useRefresh(); + const handleClick = () => { + refresh(); + } + return ; +}; +``` + +To make this work, react-admin stores a `version` number in its state. The `useDataProvider()` hook uses this `version` in its effect dependencies. Also, page components use the `version` as `key`. The `refresh` callback increases the `version`, which forces a re-execution all queries based on the `useDataProvider()` hook, and a rerender of all components using the `version` as key. + +This means that you can make any component inside a react-admin app refreshable by using the right key: + +```jsx +import * as React from 'react'; +import { useVersion } from 'react-admin'; + +const MyComponent = () => { + const version = useVersion(); + return
+ ... +
; +}; +``` + +The callback takes 1 argument: + - `hard`: when set to true, the callback empties the cache, too + +### `useUnselectAll` + +This hook returns a function that unselects all lines in the current `Datagrid`. Pass the name of the resource as argument. + +```jsx +import { useUnselectAll } from 'react-admin'; + +const UnselectAllButton = () => { + const unselectAll = useUnselectAll(); + const handleClick = () => { + unselectAll('posts'); + } + return ; +}; +``` ## Handling Side Effects In Other Hooks diff --git a/docs/Reference.md b/docs/Reference.md index d6e30346a1a..93ed72c99b6 100644 --- a/docs/Reference.md +++ b/docs/Reference.md @@ -181,13 +181,14 @@ title: "Reference" * `useLogoutIfAccessDenied` * [`useMediaQuery`](./Theming.md#usemediaquery-hook) * [`useMutation`](./Actions.md#usemutation-hook) -* [`useNotify`](./Actions.md#handling-side-effects-in-usedataprovider) +* [`useNotify`](./Actions.md#usenotify) * `usePaginationState` * [`usePermissions`](./Authentication.md#usepermissions-hook) * [`usePreferences`](https://marmelab.com/ra-enterprise/modules/ra-preferences#usepreferences-reading-and-writing-user-preferences) * [`useQuery`](./Actions.md#usequery-hook) * [`useQueryWithStore`](./Actions.md#usequerywithstore-hook) -* [`useRedirect`](./Actions.md#handling-side-effects-in-usedataprovider) +* [`useRedirect`](./Actions.md#useredirect) +* [`useRefresh`](./Actions.md#userefresh) * [`useResourceAppLocation`](https://marmelab.com/ra-enterprise/modules/ra-navigation#useresourceapplocation-access-current-resource-app-location) * `useReference` * `useReferenceArrayFieldController` @@ -206,7 +207,7 @@ title: "Reference" * [`useUpdate`](./Actions.md#useupdate) * `useUpdateLoading` * [`useUpdateMany`](./Actions.md#useupdatemany) -* [`useUnselectAll`](./Actions.md#handling-side-effects-in-usedataprovider) +* [`useUnselectAll`](./Actions.md#useunselectall) * [`useWarnWhenUnsavedChanges`](./CreateEdit.md#warning-about-unsaved-changes) * `useVersion` * [`withDataProvider`](./Actions.md#legacy-components-query-mutation-and-withdataprovider)