Skip to content

Commit

Permalink
Merge pull request #7957 from schirrel/fix/pagination-props
Browse files Browse the repository at this point in the history
Fix <Pagination> cannot be used outside a ListContext for 3.x
  • Loading branch information
fzaninotto authored Jul 20, 2022
2 parents 355ecaa + 67a4c6b commit 32af622
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 23 deletions.
5 changes: 4 additions & 1 deletion packages/ra-core/src/controller/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import ListController from './ListController';
import ListContext from './ListContext';
import ListFilterContext from './ListFilterContext';
import ListPaginationContext from './ListPaginationContext';
import ListPaginationContext, {
ListPaginationContextValue,
} from './ListPaginationContext';
import ListSortContext from './ListSortContext';
import ListBase from './ListBase';
import useRecordSelection from './useRecordSelection';
Expand Down Expand Up @@ -40,6 +42,7 @@ export {
ListContext,
ListFilterContext,
ListPaginationContext,
ListPaginationContextValue,
ListSortContext,
ListContextProvider,
useCheckMinimumRequiredProps,
Expand Down
56 changes: 36 additions & 20 deletions packages/ra-core/src/controller/useListPaginationContext.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useContext } from 'react';
import { useContext, useMemo } from 'react';
import defaults from 'lodash/defaults';

import ListPaginationContext, {
ListPaginationContextValue,
Expand All @@ -24,25 +25,40 @@ import ListPaginationContext, {
*/
const useListPaginationContext = (props?: any): ListPaginationContextValue => {
const context = useContext(ListPaginationContext);
if (!context.setPage) {
/**
* The element isn't inside a <ListPaginationContext.Provider>
*
* This may only happen when using Datagrid / SimpleList / SingleFieldList components
* outside of a List / ReferenceManyField / ReferenceArrayField -
* which isn't documented but tolerated.
* To avoid breakage in that case, fallback to props
*
* @deprecated - to be removed in 4.0
*/
if (process.env.NODE_ENV !== 'production') {
console.log(
"List components must be used inside a <ListContextProvider>. Relying on props rather than context to get List data and callbacks is deprecated and won't be supported in the next major version of react-admin."
);
}
return props;
}
return context;
return useMemo(
() =>
defaults(
{},
props != null ? extractListPaginationContextProps(props) : {},
context
),
[context, props]
);
};

/**
* Extract only the list controller props
*
* @param {Object} props Props passed to the useListContext hook
*
* @returns {ListControllerResult} List controller props
*/
const extractListPaginationContextProps = ({
loading,
page,
perPage,
setPage,
setPerPage,
total,
resource,
}) => ({
loading,
page,
perPage,
setPage,
setPerPage,
total,
resource,
});

export default useListPaginationContext;
17 changes: 17 additions & 0 deletions packages/ra-ui-materialui/src/list/pagination/Pagination.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -207,4 +207,21 @@ describe('<Pagination />', () => {
).not.toBeNull();
});
});

it('should work outside of a ListContext', () => {
const { queryByText } = render(
<ThemeProvider theme={theme}>
<Pagination
resource="posts"
setPage={() => null}
loading={false}
setPerPage={() => {}}
perPage={1}
total={2}
page={1}
/>
</ThemeProvider>
);
expect(queryByText('ra.navigation.page_rows_per_page')).not.toBeNull();
});
});
6 changes: 4 additions & 2 deletions packages/ra-ui-materialui/src/list/pagination/Pagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
useListPaginationContext,
sanitizeListRestProps,
ComponentPropType,
ListPaginationContextValue,
} from 'ra-core';

import DefaultPaginationActions from './PaginationActions';
Expand Down Expand Up @@ -122,8 +123,9 @@ Pagination.defaultProps = {
limit: <DefaultPaginationLimit />,
rowsPerPageOptions: [5, 10, 25],
};

export interface PaginationProps extends TablePaginationBaseProps {
export interface PaginationProps
extends TablePaginationBaseProps,
Partial<ListPaginationContextValue> {
rowsPerPageOptions?: number[];
actions?: FC;
limit?: ReactElement;
Expand Down

0 comments on commit 32af622

Please sign in to comment.