okwasniewski / react-native-bottom-tabs

Native Bottom Tabs for React Native
https://okwasniewski.github.io/react-native-bottom-tabs/
MIT License
619 stars 24 forks source link

[Android] FlashList receives zero dimensions during native tab transitions #123

Closed beau-house closed 2 weeks ago

beau-house commented 2 weeks ago

Description

When using FlashList within a native bottom tab navigator on Android, warnings appear about FlashList's rendered size being unusable (< 2px) despite being wrapped in a view with a valid size. This occurs specifically during tab transitions, where layout measurements temporarily report zero dimensions before stabilizing.

https://github.com/user-attachments/assets/037a167c-9a8d-4f51-a48d-899915f34f0d

Minimal Reproduction

Reproduction Steps

  1. Set up a React Native project with react-native-bottom-tabs
  2. Add at least two screens to a native bottom tab navigator
  3. Include a FlashList components within a tab screen
  4. Switch between tabs

Expected Behavior

Actual Behavior

Findings

Environment

react-native version: 0.74.5

expo version: 51.0.38

react-native-bottom-tabs Version: 0.3.1

@shopify/flash-list Version: 1.6.4

beau-house commented 2 weeks ago

As a temporary workaround I'm wrapping FlashList in the following, which only renders its children (FlashList) when stable dimensions are available.

import { LayoutChangeEvent, View } from 'react-native'
import { useCallback, useState } from 'react'

export default function StableViewWrapper({ children }: { children: React.ReactNode }) {
  const [dimensions, setDimensions] = useState({
    width: 0,
    height: 0,
    isStable: false,
  })

  const handleLayout = useCallback((event: LayoutChangeEvent) => {
    const { width, height } = event.nativeEvent.layout

    setDimensions((prev) => {
      // Only update if dimensions actually changed
      if (prev.width === width && prev.height === height) {
        return prev
      }

      return {
        width,
        height,
        isStable: width > 0 && height > 0,
      }
    })
  }, [])

  return (
    <View style={{ flex: 1 }} onLayout={handleLayout}>
      {dimensions.isStable ? children : null}
    </View>
  )
}
okwasniewski commented 2 weeks ago

Hey thanks for reporting the issue, can you try with the latest version?

This should be fixed 👍🏻

beau-house commented 2 weeks ago

I just tried with the latest version – it's fixed 👍🏻

Thank you for this library. It's awesome! Looking forward to watching it improve the React Native ecosystem as it grows.