Skip to content

Commit 920341e

Browse files
committedNov 23, 2020
Fix ReferenceField doesn't accept the emptyText prop
Closes #5573
1 parent 6caea4b commit 920341e

File tree

2 files changed

+65
-31
lines changed

2 files changed

+65
-31
lines changed
 

‎packages/ra-ui-materialui/src/field/ReferenceField.spec.tsx

+16
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,22 @@ describe('<ReferenceField />', () => {
141141
});
142142
});
143143

144+
it('should display the emptyText if the field is empty', () => {
145+
const { getByText } = renderWithRedux(
146+
<ReferenceField
147+
record={{ id: 123 }}
148+
resource="comments"
149+
source="postId"
150+
reference="posts"
151+
basePath="/comments"
152+
emptyText="EMPTY"
153+
>
154+
<TextField source="title" />
155+
</ReferenceField>
156+
);
157+
expect(getByText('EMPTY')).not.toBeNull();
158+
});
159+
144160
it('should use the reference from the store if available', () => {
145161
const { container, getByText } = renderWithRedux(
146162
<MemoryRouter>

‎packages/ra-ui-materialui/src/field/ReferenceField.tsx

+49-31
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ import PropTypes from 'prop-types';
44
import classnames from 'classnames';
55
import get from 'lodash/get';
66
import { makeStyles } from '@material-ui/core/styles';
7+
import { Typography } from '@material-ui/core';
78
import ErrorIcon from '@material-ui/icons/Error';
89
import {
910
useReference,
1011
UseReferenceProps,
1112
getResourceLinkPath,
1213
LinkToType,
1314
ResourceContextProvider,
15+
Record,
1416
} from 'ra-core';
1517

1618
import LinearProgress from '../layout/LinearProgress';
@@ -63,40 +65,21 @@ import { ClassesOverride } from '../types';
6365
* In previous versions of React-Admin, the prop `linkType` was used. It is now deprecated and replaced with `link`. However
6466
* backward-compatibility is still kept
6567
*/
66-
6768
const ReferenceField: FC<ReferenceFieldProps> = ({
68-
children,
6969
record,
7070
source,
71+
emptyText,
7172
...props
72-
}) => {
73-
if (React.Children.count(children) !== 1) {
74-
throw new Error('<ReferenceField> only accepts a single child');
75-
}
76-
const { basePath, resource } = props;
77-
const resourceLinkPath = getResourceLinkPath({
78-
...props,
79-
resource,
80-
record,
81-
source,
82-
basePath,
83-
});
84-
85-
return (
86-
<ResourceContextProvider value={props.reference}>
87-
<PureReferenceFieldView
88-
{...props}
89-
{...useReference({
90-
reference: props.reference,
91-
id: get(record, source),
92-
})}
93-
resourceLinkPath={resourceLinkPath}
94-
>
95-
{children}
96-
</PureReferenceFieldView>
97-
</ResourceContextProvider>
73+
}) =>
74+
get(record, source) == null ? (
75+
emptyText ? (
76+
<Typography component="span" variant="body2">
77+
{emptyText}
78+
</Typography>
79+
) : null
80+
) : (
81+
<NonEmptyReferenceField {...props} record={record} source={source} />
9882
);
99-
};
10083

10184
ReferenceField.propTypes = {
10285
addLabel: PropTypes.bool,
@@ -132,9 +115,9 @@ ReferenceField.defaultProps = {
132115
link: 'edit',
133116
};
134117

135-
export interface ReferenceFieldProps
118+
export interface ReferenceFieldProps<RecordType extends Record = Record>
136119
extends PublicFieldProps,
137-
InjectedFieldProps {
120+
InjectedFieldProps<RecordType> {
138121
children: ReactElement;
139122
classes?: ClassesOverride<typeof useStyles>;
140123
reference: string;
@@ -145,6 +128,41 @@ export interface ReferenceFieldProps
145128
link?: LinkToType;
146129
}
147130

131+
/**
132+
* This intermediate component is made necessary by the useReference hook,
133+
* which cannot be called conditionally when get(record, source) is empty.
134+
*/
135+
export const NonEmptyReferenceField: FC<Omit<
136+
ReferenceFieldProps,
137+
'emptyText'
138+
>> = ({ children, record, source, ...props }) => {
139+
if (React.Children.count(children) !== 1) {
140+
throw new Error('<ReferenceField> only accepts a single child');
141+
}
142+
const { basePath, resource } = props;
143+
const resourceLinkPath = getResourceLinkPath({
144+
...props,
145+
resource,
146+
record,
147+
source,
148+
basePath,
149+
});
150+
return (
151+
<ResourceContextProvider value={props.reference}>
152+
<PureReferenceFieldView
153+
{...props}
154+
{...useReference({
155+
reference: props.reference,
156+
id: get(record, source),
157+
})}
158+
resourceLinkPath={resourceLinkPath}
159+
>
160+
{children}
161+
</PureReferenceFieldView>
162+
</ResourceContextProvider>
163+
);
164+
};
165+
148166
const useStyles = makeStyles(
149167
theme => ({
150168
link: {

0 commit comments

Comments
 (0)
Please sign in to comment.