[iOS] Bottom items not rendered when scrolling to end with variable-height items (Android works fine)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 7.2k
- Forks
- 392
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 1
Description
Description
When using FlashList v2 with dynamic-sized list items (form fields with varying heights), the bottom section of the list is not rendered on iOS when scrolling to the end.
The same code works perfectly on Android, where all items are rendered correctly.
This issue is not related to the keyboard or inputs expanding — it occurs even with static items that have variable heights.
Current behavior
On iOS:
- The last few items are not displayed.
- The list footer and padding are visible, meaning the list's end is calculated, but the items just above the footer are not rendered
- Increasing
drawDistancevalues fixes the rendering issue but causes performance problems and inconsistent behavior on other forms with different item counts
On Android:
- All items render as expected with no issues
Steps to reproduce:
- Create a FlashList with 40–50+ form fields of varying heights (text inputs, dropdowns, date pickers, signature fields, etc.)
- Scroll to the bottom of the list on iOS
- Observe that some bottom items are missing or not rendered until you slightly scroll back up
- Run the same code on Android — the full list is visible and renders correctly
Expected behavior
All list items should render correctly on iOS, just as they do on Android, when scrolling to the bottom. The list should not require platform-specific drawDistance calculations to render all items properly.
Reproduction
⚠️ Note: This issue occurs in a complex production app with form fields and dynamic content. A minimal reproduction would require setting up:
- Multiple form field types with varying heights
- 40-50+ items in the list
- ScrollToIndex functionality
- Dynamic content updates
Code from production app:
<FlashList
ref={flatListRef}
data={fields}
extraData={[fields, formData?.defined, formHidden]}
renderItem={renderItem}
keyExtractor={(item, index) => {
const baseKey = item.id || item.dbId || `item_${index}`;
const typeKey = item.type || 'unknown';
return `${baseKey}_${typeKey}_${index}`;
}}
getItemType={item => item.type || 'default'}
// === ISSUE: drawDistance needs platform-specific adjustment ===
// This workaround doesn't fully work - causes issues on some forms
drawDistance={
Platform.OS === 'ios'
? Math.round(
screenContext.windowHeight *
Math.max(1.321, visibleFields?.length / 42),
)
: Math.round(screenContext.windowHeight) // Works fine on Android
}
maxItemsInRecyclePool={100}
maintainVisibleContentPosition={{
minIndexForVisible: 0,
autoscrollToTopThreshold: 1,
}}
overrideProps={{
getItemCount: () => visibleFields?.length || 0,
getItem: (data, index) => data?.[index],
}}
removeClippedSubviews={false}
scrollEventThrottle={32}
decelerationRate="fast"
nestedScrollEnabled={true}
keyboardDismissMode="interactive"
keyboardShouldPersistTaps="always"
contentContainerStyle={{
paddingBottom: screenContext.windowHeight * 0.05,
}}
viewabilityConfig={{
minimumViewTime: 100,
itemVisiblePercentThreshold: 10,
}}
/>
Expo Snack or minimal reproduction link:
Currently not available - this occurs in a production React Native app with complex form logic. Will work on creating a minimal reproduction if needed.
Platform
- iOS
- Android (works correctly)
- Web
Environment
React Native info output:
System:
OS: macOS 26.0.1
CPU: (10) arm64 Apple M4
Memory: 143.42 MB / 16.00 GB
Shell:
version: "5.9"
path: /bin/zsh
Binaries:
Node:
version: 23.11.0
path: /opt/homebrew/bin/node
Yarn:
version: 1.22.22
path: /opt/homebrew/bin/yarn
npm:
version: 10.9.2
path: /opt/homebrew/bin/npm
Watchman:
version: 2025.04.14.00
path: /opt/homebrew/bin/watchman
Managers:
CocoaPods:
version: 1.16.2
path: /Users/saif/.rbenv/shims/pod
SDKs:
iOS SDK:
Platforms:
- DriverKit 25.0
- iOS 26.0
- macOS 26.0
- tvOS 26.0
- visionOS 26.0
- watchOS 26.0
Android SDK:
API Levels:
- "35"
Build Tools:
- 35.0.0
Android NDK: Not Found
IDEs:
Android Studio: 2025.1 AI-251.26094.121.2513.14007798
Xcode:
version: 26.0.1/17A400
path: /usr/bin/xcodebuild
Languages:
Java:
version: 17.0.15
path: /usr/bin/javac
Ruby:
version: 3.2.2
path: /Users/saif/.rbenv/shims/ruby
npmPackages:
"@react-native-community/cli":
installed: 20.0.0
wanted: 20.0.0
react:
installed: 19.1.0
wanted: 19.1.0
react-native:
installed: 0.81.4
wanted: 0.81.4
react-native-macos: Not Found
npmGlobalPackages:
"*react-native*": Not Found
Android:
hermesEnabled: true
newArchEnabled: true
iOS:
hermesEnabled: true
newArchEnabled: true
FlashList version: 2.1.0
Additional context
Attempted Workaround (Not Fully Working)
We've tried implementing a platform-specific dynamic drawDistance calculation for iOS:
drawDistance={
Platform.OS === 'ios'
? Math.round(windowHeight * Math.max(1.321, visibleFields.length / 42))
: Math.round(windowHeight)
}
Why this workaround fails:
- ❌ It requires magic numbers (1.321, 42) that don't scale properly
- ❌ Different forms with different item counts need different multipliers
- ❌ When the multiplier is too high, it causes rendering issues and performance problems on some forms
- ❌ When the multiplier is too low, bottom items don't render on other forms
- ❌ It's unreliable and inconsistent across different forms in the same app
- ✅ Android works perfectly with just
Math.round(windowHeight)without any adjustments
The core issue: There's no reliable formula to calculate the correct drawDistance for iOS across different forms with varying item counts and heights. The value that fixes one form breaks another.
Analysis
- This happens only on iOS (tested on iOS 17.x, both simulator and real devices)
- Keyboard, SafeAreaView, and TextInput resizing are not related to the issue
- Appears to be a viewport measurement or virtualization issue specific to iOS layout calculations
- Setting a higher
drawDistance(e.g.,windowHeight * 1.5or using a formula based on item count) fixes the rendering but introduces other problems
Key Questions
- Why does iOS require a larger
drawDistancethan Android for the same content? - Is there a way to make FlashList automatically calculate the correct
drawDistancebased on the actual content height? - Can the viewport prediction algorithm be improved to handle variable-height items more accurately on iOS?
Root cause hypothesis: FlashList v2's viewport prediction on iOS might slightly under-measure the scrollable area when dealing with variable-height items, causing the last few items to fall outside the visible rendering window until re-scrolled. The Android implementation appears to handle this correctly.
Checklist
- I've searched existing issues and couldn't find a duplicate
- I've provided a minimal reproduction (working on it)
- I'm using the latest version of @shopify/flash-list
- I've included all required information above
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
The issue names no source files or tests and does not include a minimal reproduction. Start by reducing the production setup to a reproducible iOS case with variable-height items, then trace the list virtualization and viewport calculations. Done means the bottom items render without a platform-specific drawDistance workaround while Android behavior remains unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react-native, typescript
- Domain
- mobile
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100