InfiniteScroll
Scrolling to the bottom of the list automatically loads more data.
Install
npm install antd-mobile@5.43.0
antd-mobile is for mobile web, not React Native or Mini Programs. React 19 projects must register createRoot with unstableSetRender at the entry, or imperative APIs such as Toast and Dialog cannot render. Switch dark mode with <html data-prefers-color-scheme="dark">.
Examples come from the official Ant Design Mobile repository (MIT) at the commit published as npm 5.43.0. Presentation helpers such as DemoBlock are JGuang rewrites, not antd-mobile APIs.
Scrolling to the bottom of the list automatically loads more data.
When to Use
When users want to see new data, they can slide up the page to automatically load the data.
When the hasMore prop is true, the infinite scroll component will call the defined loadMore function when the user page scrolls to the bottom threshold (default is 250px).
Demos
InfiniteScroll
Props
| Name | Description | Type | Default |
|---|---|---|---|
| children | Rendering custom guide content | React.ReactNode | ((hasMore: boolean, failed: boolean, retry: () => void) => React.ReactNode) | Default guidance tips |
| hasMore | Whether there is more content or not | boolean | - |
| loadMore | Callback to load more | (isRetry: boolean) => Promise<void> | - |
| threshold | The threshold of the scroll bottoming distance that triggers the loading event, in pixels | number | 250 |
InfiniteScroll will automatically lock the loadMore function to avoid repeated requests, but the premise is that the loadMore function needs to return a correct Promise. The following are examples of correct and incorrect usage:
function loadMore() { // wrong
doRequest()
}
async function loadMore() { // wrong
doRequest()
}
async function loadMore() { // ok
await doRequest()
}
function loadMore() { // ok
return doRequest()
}
Customized Content
If necessary, InfiniteScroll allows custom display content, this content can contain any element, including svg and elements with css animation.
Use with search
Infinite virtualized List
An example of infinite virtualized list via using react-virtualized
Support click to retry when the request fails
FAQ
Does it support pulling down?
Pulling down is another component: PullToRefresh.
Why do I get an error when used with ahooks' useDebounceFn or useThrottleFn?
InfiniteScroll itself already contains the logic to prevent concurrent repeated requests, so please do not use it with useDebounceFn or useThrottleFn, there will be logical conflicts between them.
Why does InfiniteScroll keep loading when switching from hide to display?
When using the InfiniteScroll component, it internally detects whether the component is visible. When visible, loadMore will be called to load data; when invisible, loadMore will not be called (this is necessary to avoid unnecessary data requests). And, this checking mechanism, will happen on the first render of the component and every time it is re-rendered to ensure that the data is loaded correctly.
But in some scenarios (for example, when used with the Tabs component), you may encounter the situation where the InfiniteScroll component keeps loading and no data is loaded, such as the following example:
<Tabs>
<Tabs.Tab title='水果' key='fruits'>菠萝</Tabs.Tab>
<Tabs.Tab title='蔬菜' key='vegetables' forceRender>
<InfiniteScroll
hasMore={true}
loadMore={() => {
// When switching to this Tab, this function does not execute
}}
/>
</Tabs.Tab>
</Tabs>
Problem description: The Tabs component displays the content of the first Tab item by default, so the content of the second Tab item InfiniteScroll is not visible. But the second Tab has a forceRender property added, so its content is rendered even if it is not visible. When the InfiniteScroll component is rendered this time, since the component is not visible, the loadMore function will not be called, which is normal and as expected.
However, when we switch to the second Tab to display the InfiniteScroll component, we find that the InfiniteScroll component does not call the loadMore function, which is different from what we expected. We hope that the loadMore function will be called at this time.
Reason: When you click to switch the Tab item of the Tabs component, the highlight state of the Tabs component will be modified. At this time, the Tabs component will be re-rendered. However, it should be noted that only the content of the Tabs component itself will be re-rendered, and the InfiniteScroll component is outside the Tabs component, not the Tabs component's own content. So, when switching Tab, the InfiniteScroll component does not re-render, and it does not trigger its checking mechanism again.
Solution:
- 1: Remove the
forceRenderof the Tab where theInfiniteScrollcomponent is located (theInfiniteScrollcomponent is only rendered when the Tab is activated and displayed. At this time, the component is visible andloadMorewill be called correctly to load data) - 2: Use the
Tabscomponent through the controlled component mode (when switchingTab, update the state of the component where theInfiniteScrollcomponent is located, at this time, theInfiniteScrollcomponent will be re-rendered, and then trigger the check mechanism again. Since the component is now visible,loadMoreis called correctly to load the data), for example:
const [activeKey, setActiveKey] = useState('fruits')
<Tabs activeKey={activeKey} onChange={setActiveKey}>
...
</Tabs>