react-native-side-menuを用いると、React Nativeアプリに簡単にサイドメニューを導入することができます。 この詳しい方法について紹介します。

動作環境

この記事の内容は、次の各バージョンで動作を確認しています。

  • react-native 0.31.0
  • react-native-side-menu 0.20.0

最小限の実装方法

1. インストールする

まずは、次のコマンドでパッケージをインストールします。

$ npm install --save react-native-side-menu

2. サイドメニューでラップする

パッケージで提供されているコンポーネントを<SideMenu />コンポーネントとしてimportし、これでメインとなるコンポーネント(以下の例では<Content />)をラップします。

また、<SideMenu />にはメニューとして表示するコンポーネントを渡します。

import React, { Component } from 'react';
import { AppRegistry, Text, View } from 'react-native';
import SideMenu from 'react-native-side-menu';

class App extends Component {
  render() {
    const menu = <Menu />;

    return (
      <SideMenu menu={menu}>
        <Content />
      </SideMenu>
    );
  }
}

class Menu extends Component {
    :
}

class Content extends Component {
    :
}

AppRegistry.registerComponent('AwesomeProject', () => App);

以上で、READMEのデモのような動作を実現できます。

ナビゲーションバーを導入する

次に、ナビゲーションバーとサイドメニューを組み合わせる方法について紹介します。

<SideMenu />コンポーネントにはisOpenというプロパティがあり、ここにBooleanを渡すことでメニューの開閉を操作しています。

  :
import { AppRegistry, NavigatorIOS, Text, View } from 'react-native';
  :

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isOpen: false
    };
  }

  render() {
    const menu = <Menu />;

    return (
      <SideMenu isOpen={this.state.isOpen} menu={menu}>
        <NavigatorIOS
          initialRoute={{
            component: Content,
            leftButtonTitle: 'Menu',
            onLeftButtonPress: this.handleLeftButtonPress.bind(this),
            title: 'Awesome Project'
          }}
          style={{ flex: 1 }}
        />
      </SideMenu>
    );
  }

  handleLeftButtonPress() {
    this.setState({ isOpen: true });
  }
}

別のコンポーネントを開く

最後に、メニューをクリックした際に別のコンポーネントを開く方法を紹介します。

特筆すべき点として、<NavigatorIOS />コンポーネントにrefプロパティを設定しています。 メニューをクリックした際に、これを参照してナビゲーションバーにpushすることで、別コンポーネントを開いています。

  :
import {
  AppRegistry,
  NavigatorIOS,
  Text,
  TouchableWithoutFeedback,
  View
} from 'react-native';

class App extends Component {
    :

  render() {
    const menu = <Menu handlePress={this.handlePress.bind(this)} />;

    return (
      <SideMenu ...>
        <NavigatorIOS ... ref='navigator' ... />
      </SideMenu>
    );
  }

    :

  handlePress(menu) {
    this.setState({ isOpen: false });
    this.refs.navigator.push({
      component: menu.component,
      title: menu.title
    });
  }
}

class Menu extends Component {
  render() {
    return (
      <TouchableWithoutFeedback onPress={() => this.props.handlePress({
          component: AwesomeContent,
          title: 'Awesome Content'
        })}
        >
        <View>
          <Text>Awesome Content</Text>
        </View>
      </TouchableWithoutFeedback>
    );
  }
}

おわりに

サイドメニューは、効果的に配置することで、よりよいインタフェースを提供することができます。

いろいろなアプリのサイドメニューを研究してみると、新しい発見があるかもしれません。