Skip to content

TabBarIOS (Tabs) in AppleTV flickering when switching between tabs #15081

@rada

Description

@rada

Is this a bug report?

Yes

Have you read the Bugs section of the Contributing to React Native Guide?

Yes

Environment

  1. react-native -v: 0.46.1
  2. node -v: 6.5.0
  3. npm -v: 3.10.3
  4. yarn --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

  1. Switch to any Tab back and forth
  2. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions