1- import { useCallback , useState } from 'react' ;
1+ import { useCallback , useMemo , useState } from 'react' ;
22import { RefreshControl , useWindowDimensions , View } from 'react-native' ;
33import { type PostData } from '@/src/common/lib/polycentric-hooks' ;
44import { Post } from './Post' ;
@@ -17,8 +17,18 @@ export function ThreadList({ post, ...rest }: ThreadListProps) {
1717
1818 const { thread } = useThread ( post ) ;
1919
20- // Fall back to rendering just the subject until the server response lands.
21- const items = thread . length > 0 ? thread : [ post ] ;
20+ // Mount the subject by itself first.
21+ // Other items may or may not be available.
22+ // This is a reliable way to keep the subject at its intended scroll
23+ // position via FlashList maintainVisibleContentPosition.
24+ // Before this, we had issues with FlashList behaving differently with
25+ // cold vs warm caches at the call site.
26+ const [ isFirstLayoutComplete , setIsFirstLayoutComplete ] = useState ( false ) ;
27+
28+ const items = useMemo ( ( ) => {
29+ if ( ! isFirstLayoutComplete ) return [ post ] ;
30+ return thread . length > 0 ? thread : [ post ] ;
31+ } , [ isFirstLayoutComplete , thread , post ] ) ;
2232
2333 const subjectIndex = items . findIndex ( ( p ) => p . id === post . id ) ;
2434
@@ -32,6 +42,7 @@ export function ThreadList({ post, ...rest }: ThreadListProps) {
3242 { ...rest }
3343 data = { items }
3444 initialScrollIndex = { subjectIndex > 0 ? subjectIndex : undefined }
45+ onLoad = { ( ) => setIsFirstLayoutComplete ( true ) }
3546 keyExtractor = { ( p ) => p . id }
3647 renderItem = { ( { item, index } ) => {
3748 const above = index > 0 ? items [ index - 1 ] : null ;
0 commit comments