diff --git a/packages/ra-core/src/controller/field/useReferenceArrayFieldController.ts b/packages/ra-core/src/controller/field/useReferenceArrayFieldController.ts
index 1817942b0b8..2432b3e1bc2 100644
--- a/packages/ra-core/src/controller/field/useReferenceArrayFieldController.ts
+++ b/packages/ra-core/src/controller/field/useReferenceArrayFieldController.ts
@@ -1,23 +1,25 @@
-import { useEffect } from 'react';
-import { useDispatch, useSelector, shallowEqual } from 'react-redux';
+import { useMemo } from 'react';
import get from 'lodash/get';
-import { crudGetManyAccumulate } from '../../actions';
-import { getReferencesByIds } from '../../reducer/admin/references/oneToMany';
-import { ReduxState, Record, RecordMap, Identifier } from '../../types';
+import { Record, RecordMap, Identifier } from '../../types';
+import { useGetMany } from '../../dataProvider';
/**
* @typedef ReferenceArrayProps
* @type {Object}
- * @property {boolean} loaded: boolean indicating if the reference has already beeen loaded
- * @property {Array} ids: the list of ids.
- * @property {Object} data: Object holding the reference data by their ids
+ * @property {Array} ids the list of ids.
+ * @property {Object} data Object holding the reference data by their ids
+ * @property {Object} error the error returned by the dataProvider
+ * @property {boolean} loading is the reference currently loading
+ * @property {boolean} loaded has the reference already been loaded
* @property {string} referenceBasePath basePath of the reference
*/
interface ReferenceArrayProps {
- loaded: boolean;
ids: Identifier[];
data: RecordMap;
+ error?: any;
+ loading: boolean;
+ loaded: boolean;
referenceBasePath: string;
}
@@ -35,7 +37,7 @@ interface Option {
*
* @example
*
- * const { loaded, data, ids, referenceBasePath, currentSort } = useReferenceArrayFieldController({
+ * const { ids, data, error, loaded, loading, referenceBasePath } = useReferenceArrayFieldController({
* basePath: 'resource';
* record: { referenceIds: ['id1', 'id2']};
* reference: 'reference';
@@ -61,34 +63,25 @@ const useReferenceArrayFieldController = ({
record,
source,
}: Option): ReferenceArrayProps => {
- const dispatch = useDispatch();
- const { data, ids } = useSelector(
- getReferenceArray({ record, source, reference }),
- shallowEqual
- );
- useEffect(() => {
- dispatch(crudGetManyAccumulate(reference, ids));
- }, [reference, ids, record.id]); // eslint-disable-line react-hooks/exhaustive-deps
-
+ const ids = get(record, source) || [];
+ const { data, error, loading, loaded } = useGetMany(reference, ids);
const referenceBasePath = basePath.replace(resource, reference); // FIXME obviously very weak
-
return {
- // eslint-disable-next-line eqeqeq
- loaded: data != undefined,
ids,
- data,
+ data: useMemo(() => indexById(data), [data]),
+ error,
+ loaded,
+ loading,
referenceBasePath,
};
};
-const getReferenceArray = ({ record, source, reference }) => (
- state: ReduxState
-) => {
- const ids = get(record, source) || [];
- return {
- data: getReferencesByIds(state, reference, ids),
- ids,
- };
-};
+const indexById = (records: Record[]) =>
+ records
+ .filter(r => typeof r !== 'undefined')
+ .reduce((prev, current) => {
+ prev[current.id] = current;
+ return prev;
+ }, {});
export default useReferenceArrayFieldController;
diff --git a/packages/ra-core/src/dataProvider/useGetMany.ts b/packages/ra-core/src/dataProvider/useGetMany.ts
index a3c393c3ecd..973fc89d864 100644
--- a/packages/ra-core/src/dataProvider/useGetMany.ts
+++ b/packages/ra-core/src/dataProvider/useGetMany.ts
@@ -155,6 +155,16 @@ const callQueries = debounce(() => {
.filter(v => v != null); // remove null values
if (accumulatedIds.length === 0) {
// no need to call the data provider if all the ids are null
+ queries.forEach(({ ids, setState, onSuccess }) => {
+ setState({
+ data: emptyArray,
+ loading: false,
+ loaded: true,
+ });
+ if (onSuccess) {
+ onSuccess({ data: emptyArray });
+ }
+ });
return;
}
dataProvider(
@@ -188,4 +198,6 @@ const callQueries = debounce(() => {
});
});
+const emptyArray = [];
+
export default useGetMany;
diff --git a/packages/ra-ui-materialui/src/field/ReferenceArrayField.js b/packages/ra-ui-materialui/src/field/ReferenceArrayField.js
index df38144f4eb..9e6698d6452 100644
--- a/packages/ra-ui-materialui/src/field/ReferenceArrayField.js
+++ b/packages/ra-ui-materialui/src/field/ReferenceArrayField.js
@@ -1,4 +1,4 @@
-import React, { Children, cloneElement } from 'react';
+import React, { Children, cloneElement, memo } from 'react';
import PropTypes from 'prop-types';
import LinearProgress from '@material-ui/core/LinearProgress';
import { makeStyles } from '@material-ui/core/styles';
@@ -45,11 +45,12 @@ export const ReferenceArrayField = ({ children, ...props }) => {
}
return (
-
+ >
+ {children}
+
);
};
@@ -87,7 +88,7 @@ export const ReferenceArrayFieldView = ({
referenceBasePath,
}) => {
const classes = useStyles({ classes: classesOverride });
- if (loaded === false) {
+ if (!loaded) {
return ;
}
@@ -113,4 +114,6 @@ ReferenceArrayFieldView.propTypes = {
referenceBasePath: PropTypes.string,
};
+const PureReferenceArrayFieldView = memo(ReferenceArrayFieldView);
+
export default ReferenceArrayField;