Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

large title breaks when nested scrollview changes / it has multiple tabs with different scrollviews nested ? #1997

Open
a-eid opened this issue Dec 28, 2023 · 2 comments
Labels
Bug Something isn't working Platform: iOS This issue is specific to iOS Repro provided A reproduction with a snack or repo is provided

Comments

@a-eid
Copy link

a-eid commented Dec 28, 2023

Description

basically what I have is a single Stack that has a single tabbar screen, the first tab's scrollview pushes the large title as expected but not the others. also I'm having weird issues when enabling freezeOnBlur, unmountOnBlur or lazy.

Simulator.Screen.Recording.-.iPhone.14.-.2023-12-28.at.12.16.53.mp4

I posted a snack link, but for some reason the native stack is not working from either RNS or react navigation.

Steps to reproduce

1- create a native stack.
2- nest a tabbar as one of it's screens'
3- for each tabbar screen add a scrollview. ( properly ).

Snack or a link to a repository

https://snack.expo.dev/@aeid/ludicrous-blue-scones

Screens version

3.29.0

React Native version

0.72.6

Platforms

iOS

JavaScript runtime

Hermes

Workflow

Expo managed workflow

Architecture

Paper (Old Architecture)

Build type

Debug mode

Device

iOS simulator

Device model

iPhone 14

Acknowledgements

Yes

@github-actions github-actions bot added Repro provided A reproduction with a snack or repo is provided Platform: iOS This issue is specific to iOS labels Dec 28, 2023
@a-eid
Copy link
Author

a-eid commented Dec 28, 2023

this code reproduces the bug as well without the need for tabbar navigator.

  const [index, setIndex] = useState(0);
  useEffect(() => {
    const interval = setInterval(() => {
      setIndex((i) => i + 1);
    })

    return () => {
      clearInterval(interval);
    }
  }, [])

  return (
    <ScrollView contentInsetAdjustmentBehavior="automatic" key={index}>
      <Text style={{ marginTop: 50 }}>test</Text>
    </ScrollView>
  );

@a-eid a-eid changed the title large title breaks when it has nested tabbar ? large title breaks when nested scrollview changes / it has multiple tabs with different scrollviews nested ? Dec 28, 2023
@kkafar kkafar added the Bug Something isn't working label Dec 30, 2023
@tboba
Copy link
Member

tboba commented Feb 21, 2024

Hi @a-eid, thanks for submitting this issue! I can confirm this issue is reproducible for me.
A few remarks I've discovered so far:

  • The problem still exists while I was trying to replace the scroll view with other one after some small period of time - so the large header is not dependent on the scroll view
  • Large header on bottom tabs on Fabric does not work at all, but that's because Scroll View is not the first child of a screen - probably that's because of some wrong flattening that happens in React Navigation code. The solution is to add collapsable={true} in Background and View that wraps the children here - https://github.com/react-navigation/react-navigation/blob/main/packages/elements/src/Screen.tsx (I'll submit a PR that fixes this 🫡)
  • After fixing above problem, luckily on Fabric switching the tabs does work! But that's because of the view recykling - after turning off the view recykling (in my case I just commented the code from _enqueueComponentViewWithComponentHandle method from RCTComponentViewRegistry) gives the same result as on Paper.

Nonetheless, I still haven't got a solution about this bug, but I'll keep you informed 👍

osdnk pushed a commit to react-navigation/react-navigation that referenced this issue Feb 23, 2024
**Motivation**

This PR is a part of ongoing investigation on PR
[#1997](software-mansion/react-native-screens#1997)
in React Native Screens.
Because of how the views are being flattened, in some components (like
bottom-tabs) large title of a header does not collapse while swiping the
content vertically. That's because of an unnecessary view that is being
rendered above the ScrollView in native view hierarchy.

**Test plan**

Below you can find the code that reproduces this issue.

```tsx
import { Text, ScrollView, TouchableOpacity } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { GestureHandlerRootView } from 'react-native-gesture-handler';

const stack = createNativeStackNavigator();
const tabs = createBottomTabNavigator();

export default function App() {
  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      <NavigationContainer>
        <stack.Navigator
          screenOptions={{
            statusBarColor: 'white',
            statusBarStyle: 'dark',
            headerShown: true,
            headerLargeTitle: true,
          }}>
          <stack.Screen
            name="tabbar"
            component={Tabbar}
            options={{ title: 'Explore' }}
          />
          <stack.Screen
            name="dummiacz"
            component={Dummy}
            options={{ title: 'I am dummy' }}
          />
        </stack.Navigator>
      </NavigationContainer>
    </GestureHandlerRootView>
  );
}

export function Tabbar({ navigation }) {
  return (
    <tabs.Navigator
      screenOptions={{
        headerShown: false,
        freezeOnBlur: false,
        unmountOnBlur: false,
        lazy: true,
      }}>
      <tabs.Screen
        name="home"
        component={Dummy}
        // @ts-ignore
        listeners={{ focus: () => navigation.setOptions({ title: 'Explore' }) }}
      />
      <tabs.Screen
        name="orders"
        component={Dummy}
        // @ts-ignore
        listeners={{ focus: () => navigation.setOptions({ title: 'Orders' }) }}
      />
      <tabs.Screen
        name="cart"
        component={Dummy}
        // @ts-ignore
        listeners={{ focus: () => navigation.setOptions({ title: 'Cart' }) }}
      />
      <tabs.Screen
        name="more"
        component={Dummy}
        // @ts-ignore
        listeners={{ focus: () => navigation.setOptions({ title: 'More' }) }}
      />
    </tabs.Navigator>
  );
}

export function Dummy({ navigation }) {
  return (
    <ScrollView contentInsetAdjustmentBehavior="automatic">
      <TouchableOpacity onPress={() => navigation.navigate('dummiacz')}>
        <Text style={{ marginTop: 50 }}>Mleko</Text>
      </TouchableOpacity>
    </ScrollView>
  );
}
```

<details>
<summary>Before</summary>


https://github.com/react-navigation/react-navigation/assets/23281839/4f3b1f81-ef8c-4d4e-aea3-cd6cc1527621

In the view hierarchy there's one unnecessary view that makes large
header buggy!

<img width="379" alt="Screenshot 2024-02-21 at 15 21 05"
src="https://github.com/react-navigation/react-navigation/assets/23281839/d7552090-7419-4f61-a255-5ca271d228f0">

</details>

<details>
<summary>After</summary>


https://github.com/react-navigation/react-navigation/assets/23281839/f4ad8327-c3b3-403d-a1e1-4df0aaf40e2d

Unnecessary view is gone!
Also, we know about the bug with switching the tabs that is also visible
in the video - we're investigating it right now!

<img width="411" alt="Screenshot 2024-02-21 at 15 28 37"
src="https://github.com/react-navigation/react-navigation/assets/23281839/5ac04cbd-f830-4115-b209-44177c305c56">
</details>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Something isn't working Platform: iOS This issue is specific to iOS Repro provided A reproduction with a snack or repo is provided
Projects
None yet
Development

No branches or pull requests

3 participants