Lynx UI logo
Lynx UI

<FeedList>

A FeedList component for ReactLynx. Designed to render lists with complex layouts and infinite scrolling.
Info

You can check the source code to understand how it works, and you're welcome to submit MRs to enhance its capabilities.

Moreover, you can also implement your own feed/list interaction behavior with MTS.

Basic Usage
Under the `refreshOptions`

Basic Usage

Use FeedList when the page needs both virtualized list rendering and feed behaviors such as pull-to-refresh or load-more. Keep each row as a direct list-item child with a stable item-key, and provide listId plus listType so the underlying list can manage identity and layout.

Use loadMoreFooter for the loading state and noMoreDataFooter when the feed has reached the end. Switch between them through changeHasMoreStatus; this footer state is independent from refresh state and list diff results.

How to trigger refresh directly

Use startRefresh when refresh should be driven by a command instead of a pull gesture, such as a retry button or external filter change. After the data request finishes, call finishRefresh to release the refresh header.

FeedListProps

Properties

bounceableOptions
iOS
Android
Typeboolean | BounceableBasicProps·Defaultfalse
Accept true for default options. If you need to customize the bounceable effect, you can pass in the bounceableProps.
bounces
iOS
Typeboolean·Defaulttrue
Enable iOS bounces effect.
children
iOS
Android
Harmony
TypeReactNode
Children of list.
className
iOS
Android
Harmony
Typestring
className
crossAxisGap
iOS
Android
Harmony
Typenumber·Default0
Specifies the cross axis spacing between Component in the list.
enableScroll
iOS
Android
Harmony
Typeboolean·Defaulttrue
Enable vertical scroll.
enableScrollBar
iOS
Android
Harmony
Typeboolean·Defaultfalse
Enable scrollBar.
enableScrollMonitor
iOS
Android
Harmony
Typeboolean·Defaultfalse
Enable scroll monitor.
exposureID
iOS
Android
Harmony
Typestring
exposure-id for global exposure
exposureScene
iOS
Android
Harmony
Typestring
exposure-scene for global exposure
initialScrollIndex
iOS
Android
Harmony
Typenumber·Default0
The position to which the list automatically scrolls on the initial load.
iosEnableSimultaneousTouch
iOS
Typeboolean·Defaulttrue
Force touch event to send to List.
iosScrollsToTop
iOS
Typeboolean·Defaulttrue
Whether tapping the iOS status bar should scroll to top.
itemSnap
iOS
Android
Harmony
Type{factor: number, offset: number}
Paginated scrolling effects
listId
iOS
Android
Harmony
Typestring
The id of the list.
listMaxSize
iOS
Android
Harmony
Typenumber
Unit is px. Sets the auto-limiting size for the container. When child content size is below this value,the container size adjusts to fit content. When exceeded, the container locks at this size.
listType
iOS
Android
Harmony
Typesingle | flow | waterfall
The layout type of list.
loadMoreFooter
iOS
Android
TypeReactElement·Defaultfalse
The loadmore area of the list.
lowerThresholdItemCount
iOS
Android
Harmony
Typenumber·Default0
Will override the lower-threshold. The item threshold from the lower edge of the list to trigger the onScrollToLower event.
main-thread:gesture
iOS
Android
TypeBaseGesture
If you want to use gesture, pass it here.
mainAxisGap
iOS
Android
Harmony
Typenumber·Default0
Specifies the major axis spacing between Component in the list.
name
iOS
Android
Harmony
Typestring
The name of list.
needLayoutCompleteInfo
iOS
Android
Harmony
Typeboolean·Defaultfalse
Output layout complete detailed info.
noMoreDataFooter
iOS
Android
TypeReactElement·Defaultfalse
When no more data to be inserted and the hasMoreData method is called, the loadMoreFooter will be switched to noMoreDataFooter.
onUIAppear
iOS
Android
Harmony
Type(e: CommonEvent) => void
Exposure event for UI
onUIDisappear
iOS
Android
Harmony
Type(e: CommonEvent) => void
Disappear event for UI
preloadBufferCount
iOS
Android
Harmony
Typenumber·Default0
Controls the number of nodes to be preloaded outside the on-screen nodes of the list. Not supported when listType is set to 'waterfall'.
ref
TypeForwardedRef
refreshOptions
iOS
Android
Typeboolean | RefreshProps·Defaultfalse
Accept true for default options. If you need to customize the refresh effect, you can pass in the RefreshProps.
scrollEventThrottle
iOS
Android
Harmony
Typenumber·Default200
The time interval, in milliseconds, for the list to trigger the scroll event callback.
scrollMonitorTag
iOS
Android
Harmony
Typestring·Defaultfalse
The tag for scroll monitor.
scrollOrientation
iOS
Android
Harmony
Typevertical | horizontal·Default'vertical'
Set to 'vertical' for vertical scrolling and set to 'horizontal' for horizontal scrolling.
scrollPropagationBehavior
iOS
Android
TypeScrollPropagationBehavior·Default'native'
Controls whether scroll events propagate to parent containers. For now, 'preventPropagate' needs to be used together with temporaryBlockScrollClass and temporaryBlockScrollTag on iOS.
shouldRequestStateRestore
iOS
Android
Harmony
Typeboolean·Defaultfalse
The lifecycle of element layer reuse. It solves the problem of reuse status disorder in the UI layer.
showVisibleItemInfoInScrollEvent
iOS
Android
Harmony
Typeboolean·Defaultfalse
Controls whether the attachedCells information is included in the bindScroll event detail.
spanCount
iOS
Android
Harmony
Typenumber·Defaulttrue
The span count of list.
stickyOffset
iOS
Android
Harmony
Typenumber·Default0
The offset of the sticky position from the top or bottom of the list.
style
iOS
Android
Harmony
TypeCSSProperties
style
temporaryAndroidEnableOverflow
Android
Typeboolean·Defaulttrue
Used to control whether platform list enable overflow property on Android platform.
temporaryBlockScrollClass
iOS
Typestring·Default'BDXLynxViewPager'
The specific class name of the container that is blocked when 'scrollPropagationBehavior' is set to be 'preventPropagate', must be informed by the container provider. For now, 'preventPropagate' needs to be used together with temporaryBlockScrollClass and temporaryBlockScrollTag on iOS. This is a temporary props and will be deprecated on new Lynx SDK version.
temporaryBlockScrollTag
iOS
Typenumber·Default0
Used to specify the native container tag that is blocked when 'scrollPropagationBehavior' is set to be 'preventPropagate', corresponding to the Tag attribute of UIView. Needs to be specified by the native container provider. For now, 'preventPropagate' needs to be used together with temporaryBlockScrollClass and temporaryBlockScrollTag on iOS. This is a temporary props and will be deprecated on new Lynx SDK version.
upperThresholdItemCount
iOS
Android
Harmony
Typenumber·Default0
Will override the upper-threshold. The item threshold from the upper edge of the list to trigger the onScrollToUpper event.
useRefactorList
iOS
Android
Harmony
Typeboolean·Defaulttrue
Use refactored list.

Events

catchLongPress
iOS
Android
Harmony
Type(e: EventHandler | undefined) => void
Same as onLongPress, but stops the event from propagating to parent elements.
catchTouchCancel
iOS
Android
Harmony
Type(e: EventHandler | undefined) => void
Same as onTouchCancel, but stops the event from propagating to parent elements.
catchTouchEnd
iOS
Android
Harmony
Type(e: EventHandler | undefined) => void
Same as onTouchEnd, but stops the event from propagating to parent elements.
catchTouchMove
iOS
Android
Harmony
Type(e: EventHandler | undefined) => void
Same as onTouchMove, but stops the event from propagating to parent elements.
catchTouchStart
iOS
Android
Harmony
Type(e: EventHandler | undefined) => void
Same as onTouchStart, but stops the event from propagating to parent elements.
debugLogLevel
iOS
Android
Harmony
Type0 | 1 | 2 | 3·Default0
Display debug logs. 0: none, 1: error, 2: info, 3: verbose
onLayoutChange
iOS
Android
Harmony
Type(e: EventHandler | undefined) => void
Send when UI has changed viewport size.
onLayoutComplete
iOS
Android
Harmony
Type(e: {detail: {diffResult?: {insertions: number[], move_from: number[], move_to: number[], removals: number[], update_from: number[], update_to: number[]}, layout-id: number, visibleCellsAfterLayout?: ListItemInfo[], visibleCellsBeforeLayout?: ListItemInfo[]}}) => void
Send when list's items are updated and this update process has finished.
onLongPress
iOS
Android
Harmony
Type(e: EventHandler | undefined) => void
Send when a touch-point is held on the UI for a period of time.
onScroll
iOS
Android
Type(e: ScrollEvent) => void
Being triggered when scrolling occurs.
onScrollEnd
iOS
Android
Type(e: [object Object] | undefined) => void·Defaultundefined
Being triggered when scrolling stops.
onScrollStateChange
iOS
Android
Harmony
Type(e: ListScrollStateChangeEvent) => void
The scroll state change.
onScrollToLower
iOS
Android
Type(e: [object Object] | undefined) => void·Defaultundefined
Being triggered when scrolling to lower.
onScrollToUpper
iOS
Android
Type(e: [object Object] | undefined) => void·Defaultundefined
Being triggered when scrolling to upper.
onSnapToItem
iOS
Android
Harmony
Type(e: ListSnapEvent) => void
Send when list snaps to an item.
onTap
iOS
Android
Harmony
Type(e: EventHandler | undefined) => void
Send when a touch-point is tapped on the UI.
onTouchCancel
iOS
Android
Harmony
Type(e: EventHandler | undefined) => void
Send when a touch event is interrupted or cancelled before it is completed.
onTouchEnd
iOS
Android
Harmony
Type(e: EventHandler | undefined) => void
Send when a touch-point is removed from the UI.
onTouchMove
iOS
Android
Harmony
Type(e: EventHandler | undefined) => void
Send when a touch-point is moving on the UI.
onTouchStart
iOS
Android
Harmony
Type(e: EventHandler | undefined) => void
Send when a touch-point is placed on the UI.

headerReleased

headerSize
Typenumber
offset
Typenumber

refreshOffsetEvent

headerSize
Typenumber
isDragging
Typeboolean
offset
Typenumber

FeedListRef

autoScroll
iOS
Android
Harmony
Type(rate: px | rpx | ppx | rem | em | vw | vh, start: boolean, autoStop: boolean) => void
Scroll the list to the specified position and offset.
changeHasMoreStatus
iOS
Android
Type(hasMore: boolean) => void
When no more data has to be inserted, call this method to replace loadMoreFooter to noMoreDataFooter.
finishRefresh
iOS
Android
Type() => void
After the startrefresh event, calling this method will end the refresh state and make the refreshHeader bounces hack.
getVisibleCells
iOS
Android
Harmony
Type(success: (res: unknown) => void, fail: (res: unknown) => void) => void
Scroll the list to the specified position and offset.
scrollIntoID
iOS
Android
Harmony
Type(animated: boolean, alignTo: top | bottom | middle | none, listItemID: string, id: string, index: number, offset: number, success: (res: unknown) => void, fail: (res: unknown) => void) => void·Defaultfalse
Extends standard list's scrollTo. This method uses worklet and supports parameter id like 'scrollIntoView' method for scroll-view. As list is lazy, index is necessary in this method to find where id's component located. useRefactorList={true} is required
scrollTo
iOS
Android
Harmony
Type(animated: boolean, alignTo: top | bottom | middle | none, index: number, offset: number, success: (res: unknown) => void, fail: (res: unknown) => void) => void·Default0
Scroll the list to the specified position and offset.
startRefresh
iOS
Android
Type() => void
When enable-refresh is true, calling this function causes the refreshHeader to be fully exposed, triggering the startrefresh event. Afterwards, refreshHeader is attached to the top of List.

RefreshEvent

triggeredBy
TypestartRefresh | drag

RefreshStateChange

state
iOS
Android
Harmony
Type{DRAGGING: [object Object], IDLE: [object Object], OVER_DRAG_RELEASE: [object Object], REFRESHING: [object Object]}
Status of refreshHeader

How to Use refreshOptions

The useRefresh hook extends the useBounces hook, leveraging its core functionality while adding several key capabilities:

  • Supports a dedicated refreshHeader node (counterpart to upperBounceItem)

  • Enables pause behavior at the refreshHeader position to simulate pull-to-refresh effects

We modified rebound curve to pause at the refreshHeader boundary (refresh zone edge), remaining there until manually released via finishRefresh after data loading completes.

A complete refresh consists of four distinct phases, and the events below map to those transitions.

Events

Each phase triggers specific events:

  • onStartRefresh: The key event in phase 3 for initiating data updates.

  • onRefreshOffsetChange: Continuously fires while refreshHeader is visible, reporting its exposure percentage

  • onHeaderReleased: Triggers when releasing drag after phase 2 (beginning rebound to refreshHeader)

  • onRefreshStateChange: Fires during phase transitions, providing full state tracking:

    • IDLE: Default state (refreshHeader hidden)

    • OVER_DRAG_RELEASE: Matches onHeaderReleased timing (post-drag release)

    • REFRESHING: Matches onStartRefresh timing

    • DRAGGING: Continuous state while dragging with refreshHeader exposed

Except as otherwise noted, this work is licensed under a Creative Commons Attribution 4.0 International License, and code samples are licensed under the Apache License 2.0.