React Native タブビュー
React Native タブビューは、AndroidとiOSではreact-native-pager-view
、Web、macOS、WindowsではPanResponderを使用して実装された、React Native用のクロスプラットフォームタブビューコンポーネントです。
デフォルトではマテリアルデザインガイドラインに従っていますが、独自のタブバーを使用したり、タブバーの位置を下に変更することもできます。

このパッケージはReact Navigationと統合されていません。タブビューをReact Navigationのナビゲーションシステムと統合したい場合(例:タブバーに画面を表示し、navigation.navigate
などを使用して画面間を移動したい場合)、代わりにMaterial Top Tab Navigatorを使用してください。
インストール
このパッケージを使用するには、プロジェクトルートでターミナルを開き、次のコマンドを実行します。
- npm
- Yarn
- pnpm
npm install react-native-tab-view
yarn add react-native-tab-view
pnpm add react-native-tab-view
次に、iOSとAndroidをサポートする予定がある場合は、react-native-pager-view
をインストールします。
Expoを使用している場合は、互換性のあるバージョンのライブラリを取得するために、次のコマンドを実行します。
expo install react-native-pager-view
Expoを使用していない場合は、次のコマンドを実行します。
- npm
- Yarn
- pnpm
npm install react-native-pager-view
yarn add react-native-pager-view
pnpm add react-native-pager-view
完了です!これで、デバイス/シミュレーターでアプリをビルドして実行できます。
クイックスタート
import * as React from 'react';
import { View, useWindowDimensions } from 'react-native';
import { TabView, SceneMap } from 'react-native-tab-view';
const FirstRoute = () => (
<View style={{ flex: 1, backgroundColor: '#ff4081' }} />
);
const SecondRoute = () => (
<View style={{ flex: 1, backgroundColor: '#673ab7' }} />
);
const renderScene = SceneMap({
first: FirstRoute,
second: SecondRoute,
});
export default function TabViewExample() {
const layout = useWindowDimensions();
const [index, setIndex] = React.useState(0);
const [routes] = React.useState([
{ key: 'first', title: 'First' },
{ key: 'second', title: 'Second' },
]);
return (
<TabView
navigationState={{ index, routes }}
renderScene={renderScene}
onIndexChange={setIndex}
initialLayout={{ width: layout.width }}
/>
);
}
Snackのその他の例
APIリファレンス
このパッケージは、タブビューのレンダリングと管理に使用されるTabView
コンポーネントと、デフォルトのタブバー実装であるTabBar
コンポーネントをエクスポートします。
TabView
タブのレンダリングと管理を担当するコンテナコンポーネントです。デフォルトではマテリアルデザインスタイルに従います。
基本的な使用方法は次のようになります。
<TabView
navigationState={{ index, routes }}
onIndexChange={setIndex}
renderScene={SceneMap({
first: FirstRoute,
second: SecondRoute,
})}
/>
TabView プロパティ
navigationState
(必須
)
タブビューの状態です。状態には次のプロパティが含まれている必要があります。
index
:routes
配列内のアクティブなルートのインデックスを表す数値routes
: タブのレンダリングに使用されるルートオブジェクトのリストを含む配列
各ルートオブジェクトには、次のプロパティが含まれている必要があります。
key
: ルートを一意に識別するためのキー(必須)title
: タブバーに表示するルートのタイトルicon
: タブバーに表示するルートのアイコンaccessibilityLabel
: タブボタンのアクセシビリティラベルtestID
: タブボタンのテストID
例
{
index: 1,
routes: [
{ key: 'music', title: 'Music' },
{ key: 'albums', title: 'Albums' },
{ key: 'recents', title: 'Recents' },
{ key: 'purchased', title: 'Purchased' },
]
}
TabView
は制御されたコンポーネントであるため、onIndexChange
コールバックを介してindex
を更新する必要があります。
onIndexChange
(必須
)
タブの変更時に呼び出されるコールバックです。新しいタブのインデックスを引数として受け取ります。呼び出されたときにナビゲーション状態を更新する必要があります。そうでない場合、変更は破棄されます。
renderScene
(必須
)
タブのページとしてレンダリングするReact要素を返すコールバックです。ルートを含むオブジェクトを引数として受け取ります。
const renderScene = ({ route, jumpTo }) => {
switch (route.key) {
case 'music':
return <MusicRoute jumpTo={jumpTo} />;
case 'albums':
return <AlbumsRoute jumpTo={jumpTo} />;
}
};
個々のルートでshouldComponentUpdate
を実装してパフォーマンスを向上させる必要があります。コンポーネントを指定しやすくするために、SceneMap
ヘルパーを使用できます。
SceneMap
は、route.key
をReactコンポーネントにマッピングするオブジェクトを受け取り、renderScene
プロパティで使用できる関数を返します。
import { SceneMap } from 'react-native-tab-view';
...
const renderScene = SceneMap({
music: MusicRoute,
albums: AlbumsRoute,
});
この方法でコンポーネントを指定する方が簡単で、shouldComponentUpdate
メソッドの実装も行われます。
各シーンは次のプロパティを受け取ります。
route
: コンポーネントによってレンダリングされる現在のルートjumpTo
: 他のタブにジャンプするメソッドです。引数としてroute.key
を取ります。position
: 現在の位置を表すアニメーションノード
jumpTo
メソッドを使用して、プログラムで他のタブに移動できます。
props.jumpTo('albums');
SceneMap
でレンダリングされたすべてのシーンはReact.PureComponent
を使用して最適化されており、親のプロパティや状態が変更されても再レンダリングされません。シーンの更新方法をより細かく制御する必要がある場合(例:navigationState
が変更されなくても再レンダリングをトリガーする場合)、SceneMap
を使用する代わりにrenderScene
を直接使用してください。
重要: SceneMap
にインライン関数を渡さないでください。たとえば、次のことをしないでください。
SceneMap({
first: () => <FirstRoute foo={props.foo} />,
second: SecondRoute,
});
コンポーネントはファイルの一番上のレベルで定義してください。インライン関数を渡すと、レンダリングごとにコンポーネントが再作成され、ルート全体がアンマウントとマウントを繰り返すことになります。これはパフォーマンスに非常に悪影響を与え、ローカル状態の消失も引き起こします。
追加のプロパティを渡す必要がある場合は、カスタムrenderScene
関数を使用してください。
const renderScene = ({ route }) => {
switch (route.key) {
case 'first':
return <FirstRoute foo={this.props.foo} />;
case 'second':
return <SecondRoute />;
default:
return null;
}
};
renderTabBar
タブバーとして使用するカスタムReact要素を返すコールバックです。
import { TabBar } from 'react-native-tab-view';
...
<TabView
renderTabBar={props => <TabBar {...props} />}
...
/>
指定しない場合、デフォルトのタブバーがレンダリングされます。このプロパティを使用して、デフォルトのタブバーをカスタマイズしたり、独自のタブバーを提供したり、タブバーを完全に無効にしたりできます。
<TabView
renderTabBar={() => null}
...
/>
tabBarPosition
タブビュー内のタブバーの位置です。使用できる値は'top'
と'bottom'
です。デフォルトは'top'
です。
lazy
現在のルートを含むオブジェクトを受け取り、シーンを遅延レンダリングするかどうかを示すブール値を返す関数です。
デフォルトでは、すべてのシーンがレンダリングされ、よりスムーズなスワイプ体験を提供します。しかし、フォーカスされていないシーンのレンダリングを、ユーザーがそれらを見るまで遅らせることもできます。特定のシーンで遅延レンダリングを有効にするには、そのroute
に対してgetLazy
からtrue
を返します。
<TabView
lazy={({ route }) => route.name === 'Albums'}
...
/>
画面で遅延レンダリングを有効にすると、フォーカスされたときにレンダリングに時間がかかるのが一般的です。この短い期間にユーザーが表示するものをカスタマイズするには、renderLazyPlaceholder
プロパティを使用します。
すべてのシーンに対して遅延を有効にするブール値を渡すこともできます。
<TabView lazy />
lazyPreloadDistance
lazy
が有効になっている場合、このプロパティを使用して、隣接するいくつのルートをプリロードするかを指定できます。この値はデフォルトで0
であり、これは遅延ページがビューポートに表示されるときにロードされることを意味します。
renderLazyPlaceholder
まだレンダリングされていないルートに対してレンダリングするカスタムReact要素を返すコールバックです。ルートを含むオブジェクトを引数として受け取ります。lazy
プロパティも有効にする必要があります。
このビューは通常、ほんの一瞬だけ表示されます。軽量にしてください。
デフォルトでは、null
をレンダリングします。
keyboardDismissMode
ドラッグジェスチャーに応答してキーボードが閉じられるかどうかを示す文字列です。使用できる値は次のとおりです。
'auto'
(デフォルト): インデックスが変更されるとキーボードが閉じられます。'on-drag'
: ドラッグが始まるとキーボードが閉じられます。'none'
: ドラッグによってキーボードは閉じられません。
swipeEnabled
スワイプジェスチャーを有効にするかどうかを示すブール値です。スワイプジェスチャーはデフォルトで有効です。false
を渡すとスワイプジェスチャーは無効になりますが、ユーザーはタブバーを押してタブを切り替えることができます。
animationEnabled
タブの変更時にアニメーションを有効にします。デフォルトではtrueです。
onSwipeStart
スワイプジェスチャーが始まったときに呼び出されるコールバックです(つまり、ユーザーが画面に触れて移動させたとき)。
onSwipeEnd
スワイプジェスチャーが終了したときに呼び出されるコールバックです(つまり、ユーザーがスワイプジェスチャーの後、画面から指を離したとき)。
initialLayout
画面の初期の高さと言語を含むオブジェクトです。これを入力すると、最初のレンダリングのパフォーマンスが向上します。ほとんどのアプリでは、これは適切なデフォルトです。
<TabView
initialLayout={{ width: Dimensions.get('window').width }}
...
/>
overScrollMode
ページャーのオーバースクロールモードのデフォルト値を上書きするために使用します。auto
、always
、またはnever
を指定できます(Androidのみ)。
sceneContainerStyle
各画面をラップするビューに適用するスタイルです。オーバーフローのクリッピングなどのデフォルトスタイルを上書きするために使用できます。
pagerStyle
すべてのシーンをラップするページャービューに適用するスタイルです。
style
タブビューコンテナに適用するスタイルです。
TabBar
マテリアルデザインをテーマにしたタブバーです。タブバーをカスタマイズするには、TabView
のrenderTabBar
プロップを使用してTabBar
をレンダリングし、追加のプロップを渡す必要があります。
例えば、インジケーターの色とタブバーの背景色をカスタマイズするには、それぞれindicatorStyle
とstyle
プロップをTabBar
に渡します。
const renderTabBar = props => (
<TabBar
{...props}
indicatorStyle={{ backgroundColor: 'white' }}
style={{ backgroundColor: 'pink' }}
/>
);
//...
return (
<TabView
renderTabBar={renderTabBar}
...
/>
);
TabBar プロパティ
getLabelText
現在のルートを含むオブジェクトを受け取り、タブのラベルテキストを返す関数です。デフォルトではroute.title
を使用します。
<TabBar
getLabelText={({ route }) => route.title}
...
/>
getAccessible
現在のルートを含むオブジェクトを受け取り、タブをaccessible
としてマークするかどうかを示すブール値を返す関数です。デフォルトはtrue
です。
getAccessibilityLabel
現在のルートを含むオブジェクトを受け取り、タブボタンのアクセシビリティラベルを返す関数です。指定されている場合はデフォルトでroute.accessibilityLabel
を使用し、それ以外の場合はルートタイトルを使用します。
<TabBar
getAccessibilityLabel={({ route }) => route.accessibilityLabel}
...
/>
getTestID
現在のルートを含むオブジェクトを受け取り、テストでこのタブボタンを見つけるためのタブボタンのテストIDを返す関数です。デフォルトではroute.testID
を使用します。
<TabBar
getTestID={({ route }) => route.testID}
...
/>
renderIcon
現在のルート、フォーカス状態、色を含むオブジェクトを受け取り、アイコンとして使用されるカスタムReact要素を返す関数です。
<TabBar
renderIcon={({ route, focused, color }) => (
<Icon
name={focused ? 'albums' : 'albums-outlined'}
color={color}
/>
)}
...
/>
renderLabel
現在のルート、フォーカス状態、色を含むオブジェクトを受け取り、ラベルとして使用されるカスタムReact要素を返す関数です。
<TabBar
renderLabel={({ route, focused, color }) => (
<Text style={{ color, margin: 8 }}>
{route.title}
</Text>
)}
...
/>
renderTabBarItem
TabBarItemProps
オブジェクトを受け取り、タブボタンとして使用されるカスタムReact要素を返す関数です。
renderIndicator
現在のルートを含むオブジェクトを受け取り、タブインジケーターとして使用されるカスタムReact要素を返す関数です。
renderBadge
現在のルートを含むオブジェクトを受け取り、バッジとして使用されるカスタムReact要素を返す関数です。
onTabPress
タブを押したときに実行する関数です。押されたタブのシーンを受け取ります。スクロールトップなどを行うのに役立ちます。
デフォルトでは、タブを押すとタブも切り替わります。この動作を防ぐには、preventDefault
を呼び出します。
<TabBar
onTabPress={({ route, preventDefault }) => {
if (route.key === 'home') {
preventDefault();
// Do something else
}
}}
...
/>
onTabLongPress
タブを長押ししたときに実行する関数です。より多くのオプションを含むメニューを表示するなど。
activeColor
アクティブなタブのアイコンとラベルのカスタムカラーです。
inactiveColor
非アクティブなタブのアイコンとラベルのカスタムカラーです。
pressColor
マテリアルリップルの色(Android >= 5.0のみ)。
pressOpacity
押されたタブの不透明度(iOSとAndroid < 5.0のみ)。
scrollEnabled
タブバーをスクロール可能にするかどうかを示すブール値です。
scrollEnabled
をtrue
に設定する場合は、初期レンダリングを改善するためにtabStyle
にwidth
も指定する必要があります。
bounces
スクロール時にタブバーがバウンスするかどうかを示すブール値です。
tabStyle
タブバー内の個々のタブアイテムに適用するスタイルです。
デフォルトでは、すべてのタブアイテムはコンテナの幅に基づいて同じ事前に計算された幅を占めます。元の幅を使用する場合は、tabStyle
にwidth: 'auto'
を指定できます。
indicatorStyle
アクティブなインジケーターに適用するスタイルです。
indicatorContainerStyle
インジケーターのコンテナビューに適用するスタイルです。
labelStyle
タブアイテムラベルに適用するスタイルです。
contentContainerStyle
タブの内側のコンテナに適用するスタイルです。
style
(TabBar
)
タブバーコンテナに適用するスタイルです。
gap
タブ間のスペースを定義します。
testID
タブバーのテストIDです。テストでタブバーをスクロールするために使用できます。
最適化のヒント
不要な再レンダリングを避ける
renderScene
関数は、インデックスが変更されるたびに呼び出されます。renderScene
関数が負荷の高い処理である場合、インデックスに依存しない場合は各ルートを個別のコンポーネントに移動し、ルートコンポーネントでshouldComponentUpdate
またはReact.memo
を使用して不要な再レンダリングを防ぐことをお勧めします。
例えば、以下のようになります。
const renderScene = ({ route }) => {
switch (route.key) {
case 'home':
return (
<View style={styles.page}>
<Avatar />
<NewsFeed />
</View>
);
default:
return null;
}
};
以下の手順を実行します。
const renderScene = ({ route }) => {
switch (route.key) {
case 'home':
return <HomeComponent />;
default:
return null;
}
};
ここで、クラスコンポーネントを使用している場合は、<HomeComponent />
はPureComponent
です。
export default class HomeComponent extends React.PureComponent {
render() {
return (
<View style={styles.page}>
<Avatar />
<NewsFeed />
</View>
);
}
}
または、関数コンポーネントを使用している場合は、React.memo
でラップします。
function HomeComponent() {
return (
<View style={styles.page}>
<Avatar />
<NewsFeed />
</View>
);
}
export default React.memo(HomeComponent);
1フレームの遅延を避ける
コンテナの幅を測定する必要があるため、画面上のいくつかの要素をレンダリングする前に待機する必要があります。初期の幅を事前に知っている場合は、それを渡すことができ、測定を待つ必要はありません。ほとんどの場合、ウィンドウの幅だけです。
例えば、以下のinitialLayout
をTabView
に渡します。
const initialLayout = {
height: 0,
width: Dimensions.get('window').width,
};
タブビューは、次元の変更にも対応し、画面回転などの変化に対応して調整されます。
多数のルートの最適化
特に画像など、多数のルートがある場合、アニメーションが大幅に遅くなる可能性があります。代わりに、限定的な数のルートをレンダリングできます。
例えば、各側に2つのルートのみをレンダリングするには、以下のようにします。
const renderScene = ({ route }) => {
if (Math.abs(index - routes.indexOf(route)) > 2) {
return <View />;
}
return <MySceneComponent route={route} />;
};
ScrollView内にTabViewをレンダリングしない
垂直方向のScrollView
内にTabView
をネストすると、TabView
内でレンダリングされるFlatList
コンポーネントの最適化が無効になります。可能であれば、これを行うのを避けてください。
必要なときにルートをレンダリングするために`lazy`および`renderLazyPlaceholder`プロップを使用する
よりスムーズなタブ切り替えエクスペリエンスを提供するために、デフォルトではlazy
オプションは無効になっていますが、有効にしてプレースホルダーコンポーネントを提供することで、より優れた遅延読み込みエクスペリエンスを実現できます。lazy
を有効にすると、ルートが必要になったときにのみレンダリングすることで、初期読み込みのパフォーマンスを向上させることができます。プロップリファレンスで詳細を確認してください。