Its a simple issue that gets really annoying with AntD
The onChange fires whenever anything changes in the pagination not only when changing page number. Meaning, when you change the page size, it triggers both onShowSizeChange AND onChange. But onChange has highter priority hence it triggers last. So it sets the page back to the same one.
Now there are multiple fixes to do. For me, personalty, I do not use antd provided page sizer in pagination and i use my own custom made using select. But there are other solutions.
If you use onChange purply only for page changing then there is a simple solution - filter if the page actually changed.
In this case, if you change your page, the provided variable on onChange and your state variable current will not match, but if you change the page size, the page will remain the same with current. This allows to do a simple if check.
onChange={(pageNum) => pageNum !== current && setCurrent(pageNum)}
This way if the page number and the current page number is the same, onChange will not change the page number (to the same one) and trigger a re-render. Its good, because it also saves on performance to not re-trigger same re-renders when nothing changed. This also allows for the onShowSizeChange to kick in without being overridden.
<Pagination
current={current}
onChange={(pageNum) => pageNum !== current && setCurrent(pageNum)}
showSizeChanger={true}
onShowSizeChange={() => setCurrent(1)}
total={1000}
/>
BUT there is an issue. If you are on the last page and you change the page size - the page number will be different, by antD calculations, and hence the if will not prevent it. So the first method would be a better one.
There is, also, a 3rd method, that I can think of. But its a hacky one. Would not use it in a big App. But its not bad. Adding 2 new methods. sizeChangeLogic that is responsible for size change logic code.
const sizeChangeLogic = (current, size) => {
setSize = true;
setCurrent(1);
};
and onChangeLogic method for on change logic code
const onChangeLogic = (current, size) => {
!setSize && setCurrent(current);
};
and also include a new variable let setSize = false; after useState.
NOTE this new variable canNOT be a state. Ill explain why soon.
and the pagination itself:
<Pagination
current={current}
onShowSizeChange={sizeChangeLogic}
onChange={onChangeLogic}
showSizeChanger={true}
total={1000}
/>
The logic here is, since onShowSizeChange triggers first, will set the locla variable setSize to true and set the page num to 1. Then onChange triggers and gets the setSize value that is, rn true, invert it and check if it can change the number if its false then it can. If its true (after a size change) it will not change it. This prevents the previously mentioned bug. After the page number (current) changes, it triggers a re-render that triggers the setSizeto go back tofalse` state hence the cycle continues.
The reason you can NOT have setSize as a state is because the state value changes AFTER a re-render. So the value from false to true would not change as both onchange methods would be ran before a re-render.
Heres a 3rd method full code:
function App() {
const [current, setCurrent] = React.useState(1);
let setSize = false;
const sizeChangeLogic = (current, size) => {
setSize = true;
setCurrent(1);
};
const onChangeLogic = (current, size) => {
!setSize && setCurrent(current);
};
return (
<Pagination
current={current}
onShowSizeChange={sizeChangeLogic}
onChange={onChangeLogic}
showSizeChanger={true}
total={1000}
/>
);
}
Choose what fits you best.