-
Notifications
You must be signed in to change notification settings - Fork 45
Description
Describe the bug
When nesting SpatialNavigationVirtualizedList (SNVL) — a vertical parent with horizontal SNVL rails as children — the horizontal scrollBehavior='stick-to-start' becomes inconsistent (doesn’t snap/stick reliably), and performance degrades as the screen adds more rails/items (focus lag after a few moves, virtualization seems less effective).
To Reproduce
import React, { memo, useMemo } from 'react'
import { Text, View } from 'react-native'
import {
DefaultFocus,
SpatialNavigationFocusableView,
SpatialNavigationNode,
SpatialNavigationRoot,
SpatialNavigationVirtualizedList,
} from 'react-tv-space-navigation'
const rails = new Array(4).fill(0).map((_, r) => ({
id: `rail-${r}`,
items: new Array(10).fill(0).map((__, i) => ({ id: `r${r}-i${i}` })),
}))
const ROW_HEIGHT = 220
const TILE_W = 120
const GAP = 16
const ITEM_SIZE = TILE_W + GAP
export const Test = () => {
const data = useMemo(() => rails, [])
return (
<View
style={{
flex: 1,
overflow: 'hidden',
}}>
<SpatialNavigationRoot>
<SpatialNavigationVirtualizedList
orientation='vertical'
data={data}
itemSize={ROW_HEIGHT}
additionalItemsRendered={1}
scrollBehavior='stick-to-start'
renderItem={({ item: rail }) => (
// CHILD: horizontal SNVL per row
<SpatialNavigationVirtualizedList
orientation='horizontal'
data={rail.items}
itemSize={ITEM_SIZE}
scrollBehavior='stick-to-start' // ← doesn't work
additionalItemsRendered={1}
renderItem={({ item }) => (
<SpatialNavigationNode>
<Tile id={item.id} width={TILE_W} height={ROW_HEIGHT - GAP} />
</SpatialNavigationNode>
)}
/>
)}
/>
</SpatialNavigationRoot>
</View>
)
}
const Tile = memo(
({ id, width, height }: { id: string; width: number; height: number }) => {
const Wrapper = id === 'rail-0' ? DefaultFocus : View
return (
<Wrapper>
<SpatialNavigationFocusableView>
{({ isFocused }) => (
<View
style={{
width,
height,
backgroundColor: isFocused ? 'red' : 'blue',
justifyContent: 'center',
alignItems: 'center',
}}>
<Text
style={{
color: 'white',
fontSize: 20,
fontWeight: 'bold',
}}>
{id}
</Text>
</View>
)}
</SpatialNavigationFocusableView>
</Wrapper>
)
},
)
Observed behavior
Holding RIGHT/LEFT within a horizontal rail: after a few items, snapping to “start” doesn't work.
As more rails/items are added, overall responsiveness drops and focus moves become laggy (virtualization seems to keep more mounted than expected) - testing in release modes.
Expected behavior
- With vertical SNVL parent + horizontal SNVL children, scrollBehavior='stick-to-start' should remain reliable in each horizontal rail.
- LEFT/RIGHT within a rail and UP/DOWN between rails should be smooth.
- Virtualization should remain effective (only a small window mounted) as rails/items scale.
Library version: 5.2.0
React Native version: 0.77.0
Additional context
I followed the Pitfalls & Troubleshooting doc: every item is always wrapped in a SpatialNavigationNode / SpatialNavigationFocusableView (no conditional mounting); only inner content changes.
This issue appears specifically when the vertical container is SNVL; with a vertical SpatialNavigationScrollView, snapping is correct but performance doesn’t scale since everything stays mounted.
Questions:
- Is SNVL→SNVL nesting (vertical parent + horizontal children) officially supported?
- If yes, are there recommended props/patterns to keep scrollBehavior and virtualization stable at scale?
- If not recommended, what’s the preferred pattern for large datasets?