diff --git a/packages/ra-ui-materialui/src/field/ReferenceArrayField.spec.tsx b/packages/ra-ui-materialui/src/field/ReferenceArrayField.spec.tsx
index d6e3526113f..b3ebad26d44 100644
--- a/packages/ra-ui-materialui/src/field/ReferenceArrayField.spec.tsx
+++ b/packages/ra-ui-materialui/src/field/ReferenceArrayField.spec.tsx
@@ -10,7 +10,7 @@ import SingleFieldList from '../list/SingleFieldList';
describe('', () => {
afterEach(cleanup);
- it('should render a loading indicator when related records are not yet fetched', () => {
+ it('should render a loading indicator when related records are not yet fetched and a second has passed', async () => {
const { queryAllByRole } = render(
', () => {
);
+
+ await new Promise(resolve => setTimeout(resolve, 1001));
expect(queryAllByRole('progressbar')).toHaveLength(1);
});
diff --git a/packages/ra-ui-materialui/src/field/ReferenceArrayField.tsx b/packages/ra-ui-materialui/src/field/ReferenceArrayField.tsx
index 5da928cb5ab..04a06a546cf 100644
--- a/packages/ra-ui-materialui/src/field/ReferenceArrayField.tsx
+++ b/packages/ra-ui-materialui/src/field/ReferenceArrayField.tsx
@@ -1,7 +1,6 @@
import * as React from 'react';
import { Children, cloneElement, FC, memo, ReactElement } from 'react';
import PropTypes from 'prop-types';
-import { LinearProgress } from '@material-ui/core';
import { makeStyles } from '@material-ui/core/styles';
import {
ListContextProvider,
@@ -16,6 +15,7 @@ import {
import { fieldPropTypes, PublicFieldProps, InjectedFieldProps } from './types';
import { ClassesOverride } from '../types';
import sanitizeFieldRestProps from './sanitizeFieldRestProps';
+import { LinearProgress } from '../layout';
/**
* A container component that fetches records from another resource specified
diff --git a/packages/ra-ui-materialui/src/field/ReferenceField.spec.tsx b/packages/ra-ui-materialui/src/field/ReferenceField.spec.tsx
index b96098b7c41..a7e5a1fbffc 100644
--- a/packages/ra-ui-materialui/src/field/ReferenceField.spec.tsx
+++ b/packages/ra-ui-materialui/src/field/ReferenceField.spec.tsx
@@ -9,20 +9,43 @@ import TextField from './TextField';
describe('', () => {
afterEach(cleanup);
+ const record = { id: 123, postId: 123 };
describe('Progress bar', () => {
- it('should display a loader on mount if the reference is not in the store', () => {
+ it("should not display a loader on mount if the reference is not in the store and a second hasn't passed yet", async () => {
const { queryByRole, container } = renderWithRedux(
-
-
+
+ );
+ await new Promise(resolve => setTimeout(resolve, 500));
+ expect(queryByRole('progressbar')).toBeNull();
+ const links = container.getElementsByTagName('a');
+ expect(links).toHaveLength(0);
+ });
+ it('should display a loader on mount if the reference is not in the store and a second has passed', async () => {
+ const { queryByRole, container } = renderWithRedux(
+
+
+
);
+ await new Promise(resolve => setTimeout(resolve, 1001));
expect(queryByRole('progressbar')).not.toBeNull();
const links = container.getElementsByTagName('a');
expect(links).toHaveLength(0);
@@ -32,7 +55,7 @@ describe('', () => {
const { queryByRole, container } = renderWithRedux(
', () => {
', () => {
// @ts-ignore-line
', () => {
// @ts-ignore-line
', () => {
const { container, getByText } = renderWithRedux(
', () => {
', () => {
// @ts-ignore-line
', () => {
const { container } = render(
', () => {
it('should render no link when resourceLinkPath is not specified', () => {
const { container } = render(
only accepts a single child');
}
- const { basePath, resource } = props;
+ const { basePath, resource, reference } = props;
const resourceLinkPath = getResourceLinkPath({
...props,
resource,
@@ -147,12 +147,13 @@ export const NonEmptyReferenceField: FC
+
= props => {
...rest
} = props;
const classes = useStyles(props);
+
if (!loaded) {
return ;
}
diff --git a/packages/ra-ui-materialui/src/input/ReferenceArrayInput.spec.js b/packages/ra-ui-materialui/src/input/ReferenceArrayInput.spec.js
index bdd0d2f9fbb..6b34638f6c0 100644
--- a/packages/ra-ui-materialui/src/input/ReferenceArrayInput.spec.js
+++ b/packages/ra-ui-materialui/src/input/ReferenceArrayInput.spec.js
@@ -15,7 +15,7 @@ describe('', () => {
translate: x => `*${x}*`,
};
- it('should render a progress bar if loading is true', () => {
+ it("should not render a progress bar if loading is true and a second hasn't passed", async () => {
const MyComponent = () => MyComponent
;
const { queryByRole, queryByText } = render(
', () => {
);
+ await new Promise(resolve => setTimeout(resolve, 250));
+ expect(queryByRole('progressbar')).toBeNull();
+ expect(queryByText('MyComponent')).toBeNull();
+ });
+
+ it('should render a progress bar if loading is true and a second has passed', async () => {
+ const MyComponent = () => MyComponent
;
+ const { queryByRole, queryByText } = render(
+
+
+
+ );
+ await new Promise(resolve => setTimeout(resolve, 1001));
expect(queryByRole('progressbar')).not.toBeNull();
expect(queryByText('MyComponent')).toBeNull();
});
diff --git a/packages/ra-ui-materialui/src/input/ReferenceInput.spec.tsx b/packages/ra-ui-materialui/src/input/ReferenceInput.spec.tsx
index 2133fc801f8..6d3a250f9df 100644
--- a/packages/ra-ui-materialui/src/input/ReferenceInput.spec.tsx
+++ b/packages/ra-ui-materialui/src/input/ReferenceInput.spec.tsx
@@ -59,7 +59,7 @@ describe('', () => {
afterEach(cleanup);
- it('should render a LinearProgress if loading is true', () => {
+ it('should render a LinearProgress if loading is true and a second has passed', async () => {
const { queryByRole } = render(
', () => {
);
+ await new Promise(resolve => setTimeout(resolve, 1001));
expect(queryByRole('progressbar')).not.toBeNull();
});
+ it("should not render a LinearProgress if loading is true and a second hasn't passed", async () => {
+ const { queryByRole } = render(
+
+
+
+ );
+
+ await new Promise(resolve => setTimeout(resolve, 250));
+ expect(queryByRole('progressbar')).toBeNull();
+ });
+
it('should not render a LinearProgress if loading is false', () => {
const { queryByRole } = render(
({
@@ -24,18 +27,27 @@ const useStyles = makeStyles(
*
* @param {Object} classes CSS class names
*/
-const LinearProgress = props => {
+const LinearProgress = ({ timeout = 1000, ...props }: LinearProgressProps) => {
const { classes: classesOverride, className, ...rest } = props;
const classes = useStyles(props);
- return (
+ const oneSecondHasPassed = useTimeout(timeout);
+
+ return oneSecondHasPassed ? (
- );
+ ) : null;
};
+
LinearProgress.propTypes = {
classes: PropTypes.object,
className: PropTypes.string,
+ timeout: PropTypes.number,
};
+
// wat? TypeScript looses the displayName if we don't set it explicitly
LinearProgress.displayName = 'LinearProgress';
+export interface LinearProgressProps extends ProgressProps {
+ timeout?: number;
+}
+
export default LinearProgress;
diff --git a/packages/ra-ui-materialui/src/layout/index.ts b/packages/ra-ui-materialui/src/layout/index.ts
index 10a4e673615..7ca62dcf6e8 100644
--- a/packages/ra-ui-materialui/src/layout/index.ts
+++ b/packages/ra-ui-materialui/src/layout/index.ts
@@ -9,7 +9,7 @@ import HideOnScroll, { HideOnScrollProps } from './HideOnScroll';
import Layout, { LayoutProps } from './Layout';
import Loading from './Loading';
import LoadingPage from './LoadingPage';
-import LinearProgress from './LinearProgress';
+import LinearProgress, { LinearProgressProps } from './LinearProgress';
import LoadingIndicator from './LoadingIndicator';
import Menu, { MenuProps } from './Menu';
import MenuItemLink, { MenuItemLinkProps } from './MenuItemLink';
@@ -57,6 +57,7 @@ export type {
ErrorProps,
HideOnScrollProps,
LayoutProps,
+ LinearProgressProps,
MenuItemLinkProps,
MenuProps,
ResponsiveProps,