Skip to content

Commit dac4459

Browse files
author
Travis CI
committed
Handle redirection via onClick
1 parent 2ac4a7a commit dac4459

File tree

2 files changed

+66
-35
lines changed

2 files changed

+66
-35
lines changed

packages/ra-ui-materialui/src/list/SimpleList.spec.tsx

+33-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as React from 'react';
2-
import { render, waitFor, within } from '@testing-library/react';
2+
import { fireEvent, render, waitFor, within } from '@testing-library/react';
33
import { createMemoryHistory } from 'history';
44
import { Router } from 'react-router-dom';
55
import { ListContext } from 'ra-core';
@@ -8,7 +8,7 @@ import SimpleList from './SimpleList';
88
import TextField from '../field/TextField';
99

1010
const renderWithRouter = children => {
11-
const history = createMemoryHistory();
11+
const history = createMemoryHistory({ initialEntries: ['/posts'] });
1212

1313
return {
1414
history,
@@ -60,7 +60,7 @@ describe('<SimpleList />', () => {
6060
(record, id, basePath) => `${basePath}/${id}/details`,
6161
],
6262
])('should support %s linkType', async (_, expectedUrl, linkType) => {
63-
const { getByText } = renderWithRouter(
63+
const { history, getByText } = renderWithRouter(
6464
<ListContext.Provider
6565
value={{
6666
loaded: true,
@@ -83,10 +83,39 @@ describe('<SimpleList />', () => {
8383
</ListContext.Provider>
8484
);
8585

86+
fireEvent.click(getByText('1'));
8687
await waitFor(() => {
87-
expect(getByText('1').closest('a').getAttribute('href')).toEqual(
88+
expect(history.entries[history.length - 1].pathname).toEqual(
8889
expectedUrl
8990
);
9091
});
9192
});
93+
it('should not render a link if linkType is false', async () => {
94+
const { getByText } = renderWithRouter(
95+
<ListContext.Provider
96+
value={{
97+
loaded: true,
98+
loading: false,
99+
ids: [1, 2],
100+
data: {
101+
1: { id: 1, title: 'foo' },
102+
2: { id: 2, title: 'bar' },
103+
},
104+
total: 2,
105+
resource: 'posts',
106+
basePath: '/posts',
107+
}}
108+
>
109+
<SimpleList
110+
linkType={false}
111+
primaryText={record => record.id.toString()}
112+
secondaryText={<TextField source="title" />}
113+
/>
114+
</ListContext.Provider>
115+
);
116+
117+
await waitFor(() => {
118+
expect(getByText('1').closest('a')).toBeNull();
119+
});
120+
});
92121
});

packages/ra-ui-materialui/src/list/SimpleList.tsx

+33-31
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
import * as React from 'react';
2-
import {
3-
isValidElement,
4-
ReactNode,
5-
ReactElement,
6-
useEffect,
7-
useState,
8-
} from 'react';
2+
import { isValidElement, ReactNode, ReactElement, useCallback } from 'react';
93
import PropTypes from 'prop-types';
104
import {
115
Avatar,
@@ -18,7 +12,7 @@ import {
1812
ListItemText,
1913
} from '@material-ui/core';
2014
import { makeStyles } from '@material-ui/core/styles';
21-
import { Link } from 'react-router-dom';
15+
import { useHistory } from 'react-router-dom';
2216
import {
2317
Identifier,
2418
linkToRecord,
@@ -140,7 +134,7 @@ const SimpleList = <RecordType extends Record = Record>(
140134
resource={resource}
141135
>
142136
<ListItem
143-
button={!!linkType as any}
137+
component="div"
144138
style={
145139
rowStyle
146140
? rowStyle(data[id], rowIndex)
@@ -283,38 +277,46 @@ const LinkOrNot = (props: LinkOrNotProps) => {
283277
resource,
284278
} = props;
285279
const classes = useLinkOrNotStyles({ classes: classesOverride });
286-
const [effect, setEffect] = useState<string>(() =>
287-
linkType === 'edit' || linkType === true
288-
? linkToRecord(basePath || `/${resource}`, id)
289-
: linkToRecord(basePath || `/${resource}`, id, 'show')
290-
);
280+
const history = useHistory();
291281

292-
useEffect(() => {
293-
if (typeof linkType !== 'function') {
294-
return;
295-
}
296-
const getEffect = async () => {
297-
if (typeof linkType === 'function') {
298-
setEffect(
299-
await linkType(record, id, basePath || `/${resource}`)
300-
);
301-
}
302-
};
282+
const handleClick = useCallback(
283+
async event => {
284+
if (!linkType) return;
285+
event.persist();
303286

304-
getEffect();
305-
}, [basePath, id, linkType, record, resource]);
287+
const effect =
288+
typeof linkType === 'function'
289+
? await linkType(record, id, basePath || `/${resource}`)
290+
: linkType;
291+
switch (effect) {
292+
case true:
293+
case 'edit':
294+
history.push(linkToRecord(basePath || `/${resource}`, id));
295+
return;
296+
case 'show':
297+
history.push(
298+
linkToRecord(basePath || `/${resource}`, id, 'show')
299+
);
300+
return;
301+
default:
302+
if (effect) history.push(effect);
303+
return;
304+
}
305+
},
306+
[basePath, history, id, record, resource, linkType]
307+
);
306308

307-
return typeof effect === 'string' ? (
308-
<Link to={effect} className={classes.link}>
309+
return linkType !== false ? (
310+
<button onClick={handleClick} className={classes.link}>
309311
{children}
310-
</Link>
312+
</button>
311313
) : (
312314
<span>{children}</span>
313315
);
314316
};
315317

316318
export type FunctionLinkType = (
317-
record: Record,
319+
recordOrId: Record,
318320
id: Identifier,
319321
basePath?: string
320322
) => string | Promise<string>;

0 commit comments

Comments
 (0)