Skip to content

jankalfus/react-native-tab-view

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

React Native Tab View npm version

A cross-platform Tab View component for React Native.

This is a JavaScript-only implementation of swipeable tab views. It's super customizable, allowing you to do things like coverflow.

Features

  • Smooth animations and gestures
  • Scrollable tabs
  • Both top and bottom tab bars
  • Follows Material Design spec
  • Highly customizable

Demo

Installation

npm install --save react-native-tab-view react-addons-shallow-compare

Example

import React, { Component } from 'react';
import { View, StyleSheet } from 'react-native';
import { TabViewAnimated, TabBarTop } from 'react-native-tab-view';

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  page: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
});

export default class TabViewExample extends Component {
  state = {
    index: 0,
    routes: [
      { key: '1', title: 'First' },
      { key: '2', title: 'Second' },
    ],
  };

  _handleChangeTab = (index) => {
    this.setState({ index });
  };

  _renderHeader = (props) => {
    return <TabBarTop {...props} />;
  };

  _renderScene = ({ route }) => {
    switch (route.key) {
    case '1':
      return <View style={[ styles.page, { backgroundColor: '#ff4081' } ]} />;
    case '2':
      return <View style={[ styles.page, { backgroundColor: '#673ab7' } ]} />;
    default:
      return null;
    }
  };

  render() {
    return (
      <TabViewAnimated
        style={styles.container}
        navigationState={this.state}
        renderScene={this._renderScene}
        renderHeader={this._renderHeader}
        onRequestChangeTab={this._handleChangeTab}
      />
    );
  }
}

API

The package exposes the following components,

<TabViewTransitioner />

Container component responsible for managing tab transitions

It accepts the following props,

  • navigationState - the current navigation state
  • configureTransition - optional callback which returns a configuration for the transition, return null to disable animation
  • onRequestChangeTab - callback for when the current tab changes, should do the setState
  • onChangePosition - callback called with position value as it changes (e.g. - on swipe or tab change), avoid doing anything expensive here
  • canJumpToTab - optional callback which accepts a route, and returns a boolean indicating whether jumping to the tab is allowed
  • initialLayout - optional object containing the initial height and width, can be passed to prevent the one frame delay in rendering
  • shouldOptimizeUpdates - whether to implement a shouldComponentUpdate strategy to minimize updates, enabled by default
  • render - callback which renders the tab view, gets a special set of props as argument

<TabViewAnimated />

A convenience wrapper around <TabViewTransitioner />

It accepts the following props in addition to all the props accepted by <TabViewTransitioner /> (except render),

  • renderPager - optional callback which renders a pager responsible for handling swipes
  • renderHeader - optional callback which renders a header, useful for a top tab bar
  • renderFooter - optional callback which renders a footer, useful for a bottom tab bar
  • renderScene - callback which renders a single scene
  • lazy - whether to load tabs lazily when you start switching

<TabViewPagerPan />

Pager component based on PanResponder (default)

It accepts the following props,

  • swipeEnabled - whether to enable swipe gestures
  • swipeDistanceThreshold - minimum swipe distance to trigger page switch
  • swipeVelocityThreshold - minimum swipe velocity to trigger page switch
  • children - React Element(s) to render

<TabViewPagerScroll />

Pager component based on ScrollView

It accepts the following props,

  • swipeEnabled - whether to enable swipe gestures
  • children - React Element(s) to render

<TabViewPagerAndroid />

Pager component based on ViewPagerAndroid It accepts the following props,

  • swipeEnabled - whether to enable swipe gestures
  • children - React Element(s) to render

<TabBar />

Basic tab bar

It accepts the following props,

  • renderIcon - optional callback which receives the current scene and returns a React Element to be used as a icon
  • renderLabel - optional callback which receives the current scene and returns a React Element to be used as a label
  • renderIndicator - optional callback which receives the current scene and returns a React Element to be used as a tab indicator
  • renderBadge - optional callback which receives the current scene and returns a React Element to be used as a badge
  • onTabPress - optional callback invoked on tab press, useful for things like scroll to top
  • pressColor - color for material ripple (Android >= 5.0 only)
  • activeOpacity - opacity for pressed tab (iOS and Android < 5.0 only)
  • scrollEnabled - whether to enable scrollable tabs
  • tabWidth - optional custom tab width for scrollable tabs
  • tabStyle - style object for the tab

<TabBarTop />

Material design themed top tab bar

It accepts the following props in addition to the props accepted by <TabBar />,

  • renderLabel - optional callback which receives the current scene and returns a React Element to be used as a label
  • indicatorStyle - style object for the tab indicator
  • labelStyle - style object for the tab label

Check the type definitions for details on shape of different objects.

Caveats

<TabViewAnimated /> and <TabViewTransitioner /> implement shouldComponentUpdate to prevent unnecessary re-rendering. As a side-effect, the tabs won't re-render if something changes in the parent's state. If you need it to trigger a re-render, put it in the navigationState.

For example, consider you have a loaded property on state which should trigger re-render. You can have your state like the following -

state = {
  index: 0,
  routes: [
    { key: '1', title: 'First' },
    { key: '2', title: 'Second' },
  ],
  loaded: false,
}

Then pass this.state as the navigationState prop to <TabViewAnimated /> or <TabViewTransitioner />.

<TabViewAnimated
  navigationState={this.state}
  renderScene={this._renderPage}
  renderHeader={this._renderHeader}
  onRequestChangeTab={this._handleChangeTab}
/>

Optimization Tips

  • The renderScene function is called every time the index changes. If your renderScene function is expensive, it's good idea move it to a separate component if your renderScene function doesn't depend on the index, and apply shouldComponentUpdate to prevent unnecessary re-renders.

  • If you've a large number of routes, especially images, it can slow the animation down a lot. You can instead render a limited number of routes. In your renderScene function, do the following to render only 2 routes on each side,

    renderScene = ({ route }) => {
      if (Math.abs(this.state.navigation.index - this.state.navigation.routes.indexOf(route)) > 2) {
        return null;
      }
    
      return <MySceneComponent route={route} />;
    };

Troubleshooting

TabBar disappears or shows weird behaviour when conditionally rendering items

zIndex in React Native is buggy which results in weird behaviour when you remove adjacent items from the hierarchy. You can try setting zIndex to 0 for the TabBar to avoid the issue.

About

A cross-platform Tab View component for React Native

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages

  • JavaScript 100.0%