-
Notifications
You must be signed in to change notification settings - Fork 24.9k
Description
Is this a bug report?
Yes
Have you read the Bugs section of the Contributing to React Native Guide?
Yes
Environment
react-native -v: 0.46.1node -v: 6.5.0npm -v: 3.10.3yarn --version(if you use Yarn):
Then, specify:
- Target Platform: AppleTV
- Development Operating System: macOS Sierra (10.12.5)
- Build tools: Xcode (8.3.3)
Steps to Reproduce
- Switch to any Tab back and forth
- Switch to any Tab back and forth
Expected Behavior
The switch to any tab is smooth and without any flickering or selection falling back to previous tab.
Actual Behavior
Switching between TabBarIOS.Items is flickering and is not smooth. While selecting the new tab, It seems like first the new tab is selected, then immediately the old one and then again the new tab. This results in tab flickering when switching between the tabs. Worse case is, when the tabs render some more complex composed element. In this case, the new tab is not being selected, as the render is taking longer. Once it is rendered, we can select it but again the flickering occurs.
It looks like by the time the JS processes the received native event (tab switch) and sends an event (prop) back to Native, the tab selection falls back to the previous tab.
I have included very basic TabBar example with plain view and one text where flickering occurs. However, given the simple View is used in tabs here, switching is occasionally smooth.
Reproducible Demo
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/
import React, { Component } from 'react';
import {
AppRegistry,
Text,
View,
TabBarIOS,
} from 'react-native';
export default class tvTabBar extends Component {
_tabItems: Array<{ key: string }> = [
{ key: 'TAB 1' },
{ key: 'TAB 2' },
{ key: 'TAB 3' },
{ key: 'TAB 4' },
];
constructor(props) {
super(props);
this.state = { activeTab: 'TAB 1' };
}
_getTabItem = (key: string) => {
switch (key) {
case 'TAB 1':
return (
<View style={{ flex: 1, top: 140, borderColor: 'red', borderWidth: 10 }}>
<Text style={{ fontSize: 30 }}>TAB 1</Text>
</View>
);
case 'TAB 2':
return (
<View style={{ flex: 1, top: 140, borderColor: 'green', borderWidth: 20 }}>
<Text style={{ fontSize: 30 }}>TAB 2</Text>
</View>
);
case 'TAB 3':
return (
<View style={{ flex: 1, top: 140, borderColor: 'darkblue', borderWidth: 30 }}>
<Text style={{ fontSize: 30 }}>TAB 3</Text>
</View>
);
case 'TAB 4':
return (
<View style={{ flex: 1, top: 140, borderColor: 'deeppink', borderWidth: 40 }}>
<Text style={{ fontSize: 30 }}>TAB 4</Text>
</View>
);
default:
return null;
}
}
_setTab(key) {
return () => {
console.log('Selecting tab: ', key);
this.setState({ activeTab: key });
};
}
render() {
return (
<TabBarIOS>
{
this._tabItems.map((tabItem) => {
return (
<TabBarIOS.Item
key={tabItem.key}
onPress={this._setTab(tabItem.key)}
title={tabItem.key}
selected={tabItem.key === this.state.activeTab}
>
{ this._getTabItem(tabItem.key) }
</TabBarIOS.Item>
);
})
}
</TabBarIOS>
);
}
}
AppRegistry.registerComponent('tvTabBar', () => { return tvTabBar; });link to project in gitlab: https://gitlab.com/radamich/tvTabBar