ReactNativeにActionSheetを実装してみた

ActionSheetとは?

この下から出てきてるやつ

f:id:rskull:20170628001833p:plain

RN本体でサポートしてくれてはいるが、iOSの標準機能なので iOS用のコンポーネントになってる。

ActionSheetIOS

うーん…同じコードで両方対応したいですね…

react-native-action-sheet

そんなときはコレ

github.com

いい感じにiOSAndroid両方対応してた

Androidは(多分)見慣れたポップアップみたいな感じで表示される

expoでサンプルコードが公開されてるので、実機とアプリがあれば簡単に確認できて便利

※ expoについては省略

今回はexpoじゃなくて、通常通り react-native init app の流れからの組み込みを想定してる

組み込む

まずはプロジェクトのルートでパッケージをインストールする

$ npm install @expo/react-native-action-sheet

サンプルコードをほぼそのまま使って動くかやってみると

import React, { Component } from 'react';

import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import {
  ActionSheetProvider,
  connectActionSheet,
} from '@expo/react-native-action-sheet';

class app extends React.Component {
  render() {
    return (
      <View style={{ flex: 1 }}>
        <ActionSheetProvider>
          <ActionSheet />
        </ActionSheetProvider>
      </View>
    );
  }
}

@connectActionSheet class ActionSheet extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <View style={{ marginBottom: 30 }}>
          <Text style={{ textAlign: 'center' }}>
            Hello! This is a simple example app to demonstrate
            @exponent/react-native-action-sheet.
          </Text>
        </View>

        <TouchableOpacity
          style={{ backgroundColor: "#000" }}
          onPress={this._onOpenActionSheet}
        >
          <Text style={{ fontSize: 15, color: '#fff' }}>Open action sheet</Text>
        </TouchableOpacity>
      </View>
    );
  }

  _onOpenActionSheet = () => {
    // Same interface as https://facebook.github.io/react-native/docs/actionsheetios.html
    let options = ['Delete', 'Save', 'Cancel'];
    let destructiveButtonIndex = 0;
    let cancelButtonIndex = 2;
    this.props.showActionSheetWithOptions(
      {
        options,
        cancelButtonIndex,
        destructiveButtonIndex,
      },
      buttonIndex => {
        // Do something here depending on the button index selected
      }
    );
  };
}

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

デフォルトだと、ES2016のDecoratorがBabelで有効になってないのでエラーがでます

> 23 | @connectActionSheet class App extends React.Component {
     | ^
  24 |   render() {
  25 |     return (
  26 |       <View style={styles.container}>

こんな感じのエラー

Decoratorを使えるようにする

プラグインを入れて

$ npm install --save-dev babel-plugin-transform-decorators-legacy

.babelrc に設定を付け加える

{
  "presets": ["react-native"],
  "plugins": [
    "transform-decorators-legacy"
  ]
}

参考:Using ES2016 Decorators in React Native - Modus Create

npmインストールとかしたらプロンプトで動いてるやつ再起動してください Ctrl+Cで止めてプロジェクトルートで $ react-native start すれば動き出します

動かしてみる

iOS

f:id:rskull:20170627235432g:plain

Android

f:id:rskull:20170628000432g:plain

なんかDeprecated警告出てたけど、そのうち修正してくれるだろう…

Flwotypeに対応

Flowtype使ってるひとはチェック引っかかるので .flwoconfig に以下の内容を設定すれば大丈夫です

[options]
esproposal.decorators=ignore

参考:ES7 decorator support or a way to ignore the error · Issue #606 · facebook/flow · GitHub

感想

いい感じ ٩( ‘ω’ )و

※ 追記

特定の状況下だと使えないことがあった

rskull.hateblo.jp