diff --git a/packages/grid/data-grid/src/DataGrid.test.tsx b/packages/grid/data-grid/src/DataGrid.test.tsx index 519e402fac8d3..eb7b774134136 100644 --- a/packages/grid/data-grid/src/DataGrid.test.tsx +++ b/packages/grid/data-grid/src/DataGrid.test.tsx @@ -60,6 +60,30 @@ describe('', () => { container.firstChild.firstChild.firstChild, ); }); + + it('should apply the page prop correctly', () => { + const rows = [ + { + id: 0, + brand: 'Nike', + }, + { + id: 1, + brand: 'Addidas', + }, + { + id: 2, + brand: 'Puma', + }, + ]; + render( +
+ +
, + ); + const cell = document.querySelector('[role="cell"][aria-colindex="0"]')!; + expect(cell).to.have.text('Addidas'); + }); }); }); diff --git a/packages/grid/x-grid-modules/src/hooks/features/usePagination.ts b/packages/grid/x-grid-modules/src/hooks/features/usePagination.ts index 6cf0d4dcb1aa6..9f5f69c36c4ea 100644 --- a/packages/grid/x-grid-modules/src/hooks/features/usePagination.ts +++ b/packages/grid/x-grid-modules/src/hooks/features/usePagination.ts @@ -61,6 +61,7 @@ export const usePagination = ( ), }; const stateRef = React.useRef(initialState); + const prevPageRef = React.useRef(1); const [state, dispatch] = React.useReducer(paginationReducer, initialState); const updateState = React.useCallback( @@ -74,16 +75,22 @@ export const usePagination = ( const setPage = React.useCallback( (page: number) => { - page = stateRef.current.pageCount >= page ? page : stateRef.current.pageCount; - apiRef.current.renderPage( - stateRef.current.paginationMode === FeatureModeConstant.client ? page : 1, - ); - + let hasPageChanged = false; + if (stateRef.current.rowCount > 0) { + page = stateRef.current.pageCount >= page ? page : stateRef.current.pageCount; + apiRef.current.renderPage( + stateRef.current.paginationMode === FeatureModeConstant.client ? page : 1, + ); + hasPageChanged = true; + } const params: PageChangeParams = { ...stateRef.current, page, }; - apiRef.current.publishEvent(PAGE_CHANGED, params); + if (hasPageChanged && prevPageRef.current !== page) { + apiRef.current.publishEvent(PAGE_CHANGED, params); + prevPageRef.current = page; + } if (stateRef.current.page !== page) { updateState({ page }); } @@ -147,6 +154,17 @@ export const usePagination = ( } }, [setPageSize, logger, getAutoPageSize]); + useApiEventHandler(apiRef, PAGE_CHANGED, options.onPageChange); + useApiEventHandler(apiRef, PAGESIZE_CHANGED, options.onPageSizeChange); + + const onResize = React.useCallback(() => { + if (options.autoPageSize) { + resetAutopageSize(); + } + }, [options.autoPageSize, resetAutopageSize]); + + useApiEventHandler(apiRef, RESIZE, onResize); + React.useEffect(() => { stateRef.current = state; }, [state]); @@ -157,14 +175,6 @@ export const usePagination = ( } }, [apiRef, stateRef, apiRef.current?.isInitialised]); - React.useEffect(() => { - updateState({ paginationMode: options.paginationMode! }); - }, [options.paginationMode, updateState]); - - React.useEffect(() => { - setPage(options.page != null ? options.page : 1); - }, [options.page, setPage]); - React.useEffect(() => { const rowCount = options.rowCount == null ? rows.length : options.rowCount; if (rowCount !== state.rowCount) { @@ -172,9 +182,7 @@ export const usePagination = ( const newPageCount = getPageCount(state.pageSize, rowCount); updateState({ pageCount: newPageCount, rowCount }); - if (state.page > newPageCount) { - setPage(newPageCount); - } + setPage(state.page); } }, [ rows.length, @@ -187,6 +195,14 @@ export const usePagination = ( state.page, ]); + React.useEffect(() => { + updateState({ paginationMode: options.paginationMode! }); + }, [options.paginationMode, updateState]); + + React.useEffect(() => { + setPage(options.page != null ? options.page : 1); + }, [options.page, setPage]); + React.useEffect(() => { if ( !options.autoPageSize && @@ -203,17 +219,6 @@ export const usePagination = ( } }, [options.autoPageSize, resetAutopageSize, columns.visible.length]); - useApiEventHandler(apiRef, PAGE_CHANGED, options.onPageChange); - useApiEventHandler(apiRef, PAGESIZE_CHANGED, options.onPageSizeChange); - - const onResize = React.useCallback(() => { - if (options.autoPageSize) { - resetAutopageSize(); - } - }, [options.autoPageSize, resetAutopageSize]); - - useApiEventHandler(apiRef, RESIZE, onResize); - const paginationApi: PaginationApi = { setPageSize, setPage, diff --git a/packages/grid/x-grid/src/XGrid.test.tsx b/packages/grid/x-grid/src/XGrid.test.tsx index 15b4b6a3f93dd..29fae4d49884f 100644 --- a/packages/grid/x-grid/src/XGrid.test.tsx +++ b/packages/grid/x-grid/src/XGrid.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { screen, createClientRender, act, fireEvent } from 'test/utils'; import { expect } from 'chai'; -import { XGrid } from '@material-ui/x-grid'; +import { XGrid, useApiRef } from '@material-ui/x-grid'; import { useData } from 'packages/storybook/src/hooks/useData'; function getActiveCell() { @@ -212,6 +212,42 @@ describe('', () => { expect(row).to.not.have.class('Mui-selected'); expect(checkbox).to.have.property('checked', false); }); + it('should apply setPage correctly', () => { + const rows = [ + { + id: 0, + brand: 'Nike', + }, + { + id: 1, + brand: 'Addidas', + }, + { + id: 2, + brand: 'Puma', + }, + ]; + const GridTest = () => { + const apiRef = useApiRef(); + React.useEffect(() => { + apiRef.current.setPage(2); + }); + return ( +
+ +
+ ); + }; + render(); + const cell = document.querySelector('[role="cell"][aria-colindex="0"]')!; + expect(cell).to.have.text('Addidas'); + }); }); describe('sorting', () => { diff --git a/packages/storybook/src/stories/grid-pagination.stories.tsx b/packages/storybook/src/stories/grid-pagination.stories.tsx index 76f0b9a136e52..bc949627fa72a 100644 --- a/packages/storybook/src/stories/grid-pagination.stories.tsx +++ b/packages/storybook/src/stories/grid-pagination.stories.tsx @@ -264,3 +264,55 @@ export function ServerPaginationWithEventHandler() { ); } +export function Page1Prop() { + const data = useData(2000, 200); + + return ( +
+ action('pageChange')(p)} + /> +
+ ); +} +export function Page2Prop() { + const data = useData(2000, 200); + + return ( +
+ action('pageChange')(p)} + /> +
+ ); +} +export function Page2Api() { + const data = useData(2000, 200); + const apiRef = useApiRef(); + + React.useEffect(() => { + apiRef.current.setPage(2); + }, [apiRef]); + + return ( +
+ action('pageChange')(p)} + /> +
+ ); +}