diff --git a/packages/ra-ui-materialui/src/list/SimpleList.spec.tsx b/packages/ra-ui-materialui/src/list/SimpleList.spec.tsx
index 7181d94aed0..ae5350f12dd 100644
--- a/packages/ra-ui-materialui/src/list/SimpleList.spec.tsx
+++ b/packages/ra-ui-materialui/src/list/SimpleList.spec.tsx
@@ -1,5 +1,5 @@
import * as React from 'react';
-import { render, waitFor, within } from '@testing-library/react';
+import { fireEvent, render, waitFor, within } from '@testing-library/react';
import { createMemoryHistory } from 'history';
import { Router } from 'react-router-dom';
import { ListContext } from 'ra-core';
@@ -8,7 +8,7 @@ import SimpleList from './SimpleList';
import TextField from '../field/TextField';
const renderWithRouter = children => {
- const history = createMemoryHistory();
+ const history = createMemoryHistory({ initialEntries: ['/posts'] });
return {
history,
@@ -60,7 +60,7 @@ describe('', () => {
(record, id, basePath) => `${basePath}/${id}/details`,
],
])('should support %s linkType', async (_, expectedUrl, linkType) => {
- const { getByText } = renderWithRouter(
+ const { history, getByText } = renderWithRouter(
', () => {
);
+ fireEvent.click(getByText('1'));
await waitFor(() => {
- expect(getByText('1').closest('a').getAttribute('href')).toEqual(
+ expect(history.entries[history.length - 1].pathname).toEqual(
expectedUrl
);
});
});
+ it('should not render a link if linkType is false', async () => {
+ const { getByText } = renderWithRouter(
+
+ record.id.toString()}
+ secondaryText={}
+ />
+
+ );
+
+ await waitFor(() => {
+ expect(getByText('1').closest('a')).toBeNull();
+ });
+ });
});
diff --git a/packages/ra-ui-materialui/src/list/SimpleList.tsx b/packages/ra-ui-materialui/src/list/SimpleList.tsx
index 9bc4d526b12..ef34b2a7aa3 100644
--- a/packages/ra-ui-materialui/src/list/SimpleList.tsx
+++ b/packages/ra-ui-materialui/src/list/SimpleList.tsx
@@ -1,11 +1,5 @@
import * as React from 'react';
-import {
- isValidElement,
- ReactNode,
- ReactElement,
- useEffect,
- useState,
-} from 'react';
+import { isValidElement, ReactNode, ReactElement, useCallback } from 'react';
import PropTypes from 'prop-types';
import {
Avatar,
@@ -18,7 +12,7 @@ import {
ListItemText,
} from '@material-ui/core';
import { makeStyles } from '@material-ui/core/styles';
-import { Link } from 'react-router-dom';
+import { useHistory } from 'react-router-dom';
import {
Identifier,
linkToRecord,
@@ -140,7 +134,7 @@ const SimpleList = (
resource={resource}
>
{
resource,
} = props;
const classes = useLinkOrNotStyles({ classes: classesOverride });
- const [effect, setEffect] = useState(() =>
- linkType === 'edit' || linkType === true
- ? linkToRecord(basePath || `/${resource}`, id)
- : linkToRecord(basePath || `/${resource}`, id, 'show')
- );
+ const history = useHistory();
- useEffect(() => {
- if (typeof linkType !== 'function') {
- return;
- }
- const getEffect = async () => {
- if (typeof linkType === 'function') {
- setEffect(
- await linkType(record, id, basePath || `/${resource}`)
- );
- }
- };
+ const handleClick = useCallback(
+ async event => {
+ if (!linkType) return;
+ event.persist();
- getEffect();
- }, [basePath, id, linkType, record, resource]);
+ const effect =
+ typeof linkType === 'function'
+ ? await linkType(record, id, basePath || `/${resource}`)
+ : linkType;
+ switch (effect) {
+ case true:
+ case 'edit':
+ history.push(linkToRecord(basePath || `/${resource}`, id));
+ return;
+ case 'show':
+ history.push(
+ linkToRecord(basePath || `/${resource}`, id, 'show')
+ );
+ return;
+ default:
+ if (effect) history.push(effect);
+ return;
+ }
+ },
+ [basePath, history, id, record, resource, linkType]
+ );
- return typeof effect === 'string' ? (
-
+ return linkType !== false ? (
+
) : (
{children}
);
};
export type FunctionLinkType = (
- record: Record,
+ recordOrId: Record,
id: Identifier,
basePath?: string
) => string | Promise;