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

fix(Android): onLayout calls in bottom tabs with freezeOnBlur #2363

Draft
wants to merge 16 commits into
base: main
Choose a base branch
from
Draft
2 changes: 1 addition & 1 deletion android/src/main/java/com/swmansion/rnscreens/Screen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ class Screen(
r: Int,
b: Int,
) {
if (container is ScreenStack && changed) {
if (changed) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was added since the logic inside is intended only for native-stack. So I have no idea why removing it would change anything. Can we have more information?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@WoLewicki I updated the description with some more information. That's all I got, I'll keep on investigating.

val width = r - l
val height = b - t

Expand Down
120 changes: 80 additions & 40 deletions apps/src/tests/TestFreeze.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,35 @@
import React, { useState, useEffect } from 'react';
import { View, Text, Button, ScrollView } from 'react-native';
import { NavigationContainer, ParamListBase } from '@react-navigation/native';
// import {createStackNavigator} from '@react-navigation/stack';
import { View, Text, Button, StyleSheet } from 'react-native';
import {
NavigationContainer,
ParamListBase,
RouteProp,
} from '@react-navigation/native';
import {
createNativeStackNavigator,
NativeStackNavigationProp,
} from '@react-navigation/native-stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

function TabScreen({ route }: { route: RouteProp<ParamListBase> }) {
const [state, setState] = useState(false);
const name = '[' + route.name.toUpperCase() + ']';
console.log(name, 'render');

return (
<View
style={styles.container}
onLayout={e => {
console.log(name, 'screen onLayout', e.nativeEvent.layout);
setState(!state);
}}>
<Text style={styles.title}>{name}</Text>
<Text style={styles.text}>
Rotate device - only "{name}" logs should appear
</Text>
</View>
);
}

const store = new Set<Dispatch>();

Expand All @@ -19,53 +43,40 @@ function useValue() {
setValue(value);
};
store.add(dispatch);
return () => store.delete(dispatch);
return () => {
store.delete(dispatch);
};
}, [setValue]);

return value;
}

function HomeScreen({
navigation,
}: {
navigation: NativeStackNavigationProp<ParamListBase>;
}) {
const value = useValue();
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen {value}</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}

function DetailsScreen({
function StackScreen({
navigation,
}: {
navigation: NativeStackNavigationProp<ParamListBase>;
}) {
const value = useValue();
// only 1 'render' should appear at the time
console.log('render', value);

return (
<ScrollView>
<View style={{ height: 400 }} />
<Text style={{ alignSelf: 'center' }}>Details Screen {value}</Text>
<View style={styles.container}>
<Text style={styles.title}>Stack Screen</Text>
<Text style={styles.text}>
Push more screens - only one 'render' should log at a time (max. 2 on
fabric)
</Text>
<Button
title="Go to Details"
onPress={() => navigation.push('Details')}
title="Push more screens"
onPress={() => navigation.push('Screen')}
/>
<View style={{ height: 800 }} />
</ScrollView>
</View>
);
}

const Stack = createNativeStackNavigator();

function App() {
function StackNavigator() {
useEffect(() => {
let timer = 0;
const interval = setInterval(() => {
Expand All @@ -75,18 +86,47 @@ function App() {
return () => clearInterval(interval);
}, []);

return (
<Stack.Navigator screenOptions={{ freezeOnBlur: true }}>
<Stack.Screen name="Screen" component={StackScreen} />
</Stack.Navigator>
);
}

const Tab = createBottomTabNavigator();

export default function App() {
return (
<NavigationContainer>
<Stack.Navigator
initialRouteName="Home"
screenOptions={{
freezeOnBlur: true,
}}>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
<Tab.Navigator screenOptions={{ freezeOnBlur: true }}>
<Tab.Screen name="First Tab" component={TabScreen} />
<Tab.Screen name="Second Tab" component={TabScreen} />
<Tab.Screen name="Third Tab" component={TabScreen} />
<Tab.Screen
name="Native Stack"
component={StackNavigator}
options={{ headerShown: false }}
/>
</Tab.Navigator>
</NavigationContainer>
);
}

export default App;
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
gap: 20,
},
title: {
fontSize: 24,
fontWeight: 'bold',
textAlign: 'center',
color: 'black',
},
text: {
textAlign: 'center',
color: 'black',
},
});
Loading