Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply review on useList #6378

Merged
merged 3 commits into from
Jun 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ const useReferenceArrayFieldController = (
const {
basePath,
filter = defaultFilter,
page: initialPage = 1,
perPage: initialPerPage = 1000,
page = 1,
perPage = 1000,
record,
reference,
sort: initialSort = defaultSort,
sort = defaultSort,
source,
} = props;
const resource = useResourceContext(props);
Expand Down Expand Up @@ -87,15 +87,15 @@ const useReferenceArrayFieldController = (
);

const listProps = useList({
data,
error,
filter,
initialData: data,
initialIds: ids,
initialPage,
initialPerPage,
initialSort,
loading,
ids,
loaded,
loading,
page,
perPage,
sort,
});

return {
Expand Down
28 changes: 14 additions & 14 deletions packages/ra-core/src/controller/useList.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ describe('<useList />', () => {

render(
<UseList
initialData={data}
initialIds={ids}
data={data}
ids={ids}
loaded
loading
filter={{ title: 'world' }}
initialSort={{ field: 'id', order: 'ASC' }}
sort={{ field: 'id', order: 'ASC' }}
callback={callback}
/>
);
Expand Down Expand Up @@ -60,12 +60,12 @@ describe('<useList />', () => {

render(
<UseList
initialData={data}
initialIds={ids}
data={data}
ids={ids}
loaded
loading
filter={{ items: ['two', 'four', 'five'] }}
initialSort={{ field: 'id', order: 'ASC' }}
sort={{ field: 'id', order: 'ASC' }}
callback={callback}
/>
);
Expand Down Expand Up @@ -98,11 +98,11 @@ describe('<useList />', () => {

render(
<UseList
initialData={data}
initialIds={ids}
data={data}
ids={ids}
loaded
loading
initialSort={{ field: 'title', order: 'DESC' }}
sort={{ field: 'title', order: 'DESC' }}
callback={callback}
/>
);
Expand Down Expand Up @@ -139,13 +139,13 @@ describe('<useList />', () => {

render(
<UseList
initialData={data}
initialIds={ids}
data={data}
ids={ids}
loaded
loading
initialSort={{ field: 'id', order: 'ASC' }}
initialPage={2}
initialPerPage={5}
sort={{ field: 'id', order: 'ASC' }}
page={2}
perPage={5}
callback={callback}
/>
);
Expand Down
97 changes: 46 additions & 51 deletions packages/ra-core/src/controller/useList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ import { useCallback, useEffect, useRef } from 'react';
import get from 'lodash/get';
import isEqual from 'lodash/isEqual';
import { indexById, removeEmpty, useSafeSetState } from '../util';
import { Identifier, Record, RecordMap, SortPayload } from '../types';
import {
FilterPayload,
Identifier,
Record,
RecordMap,
SortPayload,
} from '../types';
import usePaginationState from './usePaginationState';
import useSortState from './useSortState';
import useSelectionState from './useSelectionState';
Expand Down Expand Up @@ -38,31 +44,28 @@ import { ListControllerProps } from '.';
* );
* };
*
* @param {UseListOptions} props Also optionally accepts all the ListController props
* @param {Record[]} props.initialData An array of records
* @param {Identifier[]} props.initialIds An array of the record identifiers
* @param {UseListOptions} props
* @param {Record[]} props.data An array of records
* @param {Identifier[]} props.ids An array of the record identifiers
* @param {Boolean} props.loaded: A boolean indicating whether the data has been loaded at least once
* @param {Boolean} props.loading: A boolean indicating whether the data is being loaded
* @param {Error | String} props.error: Optional. The error if any occured while loading the data
* @param {Object} props.filter: Optional. An object containing the filters applied on the data
* @param {Number} props.initialPage: Optional. The initial page index
* @param {Number} props.initialPerPage: Optional. The initial page size
* @param {SortPayload} props.initialSort: Optional. The initial sort (field and order)
* @param {Number} props.page: Optional. The initial page index
* @param {Number} props.perPage: Optional. The initial page size
* @param {SortPayload} props.sort: Optional. The initial sort (field and order)
*/
export const useList = (props: UseListOptions): UseListValue => {
const {
data,
error,
filter = defaultFilter,
ids,
initialData,
initialIds,
loaded,
loading,
initialPage = 1,
initialPerPage = 1000,
initialSort = defaultSort,
total,
page: initialPage = 1,
perPage: initialPerPage = 1000,
sort: initialSort = defaultSort,
} = props;
const [loadingState, setLoadingState] = useSafeSetState<boolean>(loading);
const [loadedState, setLoadedState] = useSafeSetState<boolean>(loaded);
Expand All @@ -71,8 +74,8 @@ export const useList = (props: UseListOptions): UseListValue => {
data: RecordMap;
ids: Identifier[];
}>(() => ({
data: indexById(initialData),
ids: initialIds,
data: indexById(data),
ids,
}));

// pagination logic
Expand Down Expand Up @@ -156,13 +159,9 @@ export const useList = (props: UseListOptions): UseListValue => {
// We do all the data processing (filtering, sorting, paginating) client-side
useEffect(() => {
if (!loaded) return;
// Assume that if setFilters is provided then so are methods for pagination and sorting
if (props.setFilters) {
return;
}

// 1. filter
let tempData = initialData.filter(record =>
let tempData = data.filter(record =>
Object.entries(filterValues).every(([filterName, filterValue]) => {
const recordValue = get(record, filterName);
const result = Array.isArray(recordValue)
Expand Down Expand Up @@ -199,12 +198,11 @@ export const useList = (props: UseListOptions): UseListValue => {
ids: finalIds,
});
}, [
initialData,
data,
filterValues,
loaded,
page,
perPage,
props.setFilters,
setFinalItems,
sort.field,
sort.order,
Expand All @@ -223,43 +221,40 @@ export const useList = (props: UseListOptions): UseListValue => {
}, [loading, loadingState, setLoadingState]);

return {
currentSort: props.currentSort || sort,
data: data || finalItems.data,
currentSort: sort,
data: finalItems.data,
error,
displayedFilters: props.displayedFilters || displayedFilters,
filterValues: props.filterValues || filterValues,
hideFilter: props.hideFilter || hideFilter,
ids: ids || finalItems.ids,
displayedFilters,
filterValues,
hideFilter,
ids: finalItems.ids,
loaded: loadedState,
loading: loadingState,
onSelect: props.onSelect || onSelect,
onToggleItem: props.onToggleItem || onToggleItem,
onUnselectItems: props.onUnselectItems || onUnselectItems,
page: props.page || page,
perPage: props.perPage || perPage,
selectedIds: props.selectedIds || selectedIds,
setFilters: props.setFilters || setFilters,
setPage: props.setPage || setPage,
setPerPage: props.setPerPage || setPerPage,
setSort: props.setSort || setSort,
showFilter: props.showFilter || showFilter,
total: total || finalItems.ids.length,
onSelect,
onToggleItem,
onUnselectItems,
page,
perPage,
selectedIds,
setFilters,
setPage,
setPerPage,
setSort,
showFilter,
total: finalItems.ids.length,
};
};

export interface UseListOptions
extends Partial<
Omit<ListControllerProps, 'resource' | 'basePath' | 'refetch'>
> {
export interface UseListOptions<RecordType extends Record = Record> {
data: RecordType[];
ids: Identifier[];
error?: any;
filter?: any;
initialPage?: number;
initialPerPage?: number;
initialSort?: SortPayload;
initialData: Record[];
initialIds: Identifier[];
loaded: boolean;
filter?: FilterPayload;
loading: boolean;
loaded: boolean;
page?: number;
perPage?: number;
sort?: SortPayload;
}

export type UseListValue = Omit<
Expand Down