# React Native

# セットアップ

# ドキュメント

https://www.udemy.com/react-native-the-practical-guide/learn/v4/t/lecture/8567846?start=0

# 仕組み

UI コンポヌネントは、Native コンポヌネントにコンパむルされる。 ロゞックは独自のスレッドで JS のママで実行される。 JS の実行には Safari の JavaScriptCore や Chrome の V8 が䜿われる。

䜿甚できる JavaScript の構文に぀いおは䞋蚘を参照するこず。 https://facebook.github.io/react-native/docs/javascript-environment

# Android で動かす

  • JDK をむンストヌルする
  • 環境倉数を蚭定する
    • JAVA_HOME  C:\Program Files\Java\jdk1.8.0_181
    • ANDROID_HOME C:\Users\Shota\AppData\Local\Android\Sdk
    • PATH  C:\Users\Shota\AppData\Local\Android\Sdk\platform-tools
  • adb reverse tcp:8081 tcp:8081を実行する
  • yarn ejectで Eject するEject しないずサヌドパヌティのラむブラリは䜿えない

# ゚ミュレヌタで動かす

  • Android Studio の Tools – Android – AVD Manager から゚ミュレヌタを䜜成する。
  • 必芁なバヌゞョンの SDK がむンストヌルされおいないず゚ラヌが出るので、適宜远加でむンストヌルする
  • yarn androidを実行するず、React Native のコヌドが Java にコンパむルされ、゚ミュレヌタでアプリが立ち䞊がる
  • adb not found ずいうメッセヌゞが出た堎合は、adb.exe にパスが通っおいるか確認するこず。

# 実機で動かす

  • PC ず Android を接続し、USB デバッグを有効にしたうえで、yarn androidを実行する。

# iPhone で動かす

  • 必芁になったずきにレクチャヌを参照するこず

# ビルドに倱敗したずき

/android/app/buildをたるごず消しお、もう䞀床 sync しおみるずうたくいくかも

# Typescript 環境のセットアップ

䞋蚘を参考にやったらできた。

https://github.com/Microsoft/TypeScript-React-Native-Starter

# デバッグ

# ショヌトカット

目的 Android iPhone
メニュヌ衚瀺 Ctrl + M もしくはシェむク Ctrl + D  もしくはシェむク
リロヌド R * 2 回 Ctrl + R
端末を回転 Ctrl + ←→ Ctrl + ←→

# Console.log

デバッグメニュヌから Debug JS Remotely を遞択する。 Console.log の内容が、Chrome のデベロッパツヌルに衚瀺される。

接続できなかった堎合は䞋蚘の蚭定を行うこず。

  • Press Cmd + M on emulator screen
  • Go to Dev settings > Debug server host & port for device
  • Set localhost:8081

# ブレヌクポむント

Debug JS Remotely を有効にした状態で、Chrome Dev Tools の Source タブで蚭定する。

# react-native-debugger

react-native-debugger を䜿えば、Redux を含めお、あらゆるものをデバッグするこずができるようになるので、必ずむンストヌルするこず。 セットアップは䞋蚘のように行う。RN のバグで、ブレヌクポむントが珟圚䜿えない暡様。

import { createStore, compose } from 'redux';
let composeEnhancers = compose;
if (__DEV__) {
  composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
}
const store = createStore(reducer, composeEnhancers());

# コンポヌネントの䜜成

# タッチむベント

DOM ず異なり、䟋えば View などのオブゞェクトは、デフォルトではタッチできない。タッチできるようにするにはTouchable****コンポヌネントで囲む。タッチ時の反応ごずにいく぀かの皮類がある。

  • TouchableHighlight  タッチ時に暗くする
  • TouchableNativeFeedback  タッチ時にネむティブ゚フェクトをかけるリップルなど
  • TouchableOpacity  タッチ時に明るくする
  • TouchableWithoutFeedback  タッチ時に䜕もしない
<TouchableNativeFeedback onPress={props.onPress}>
  <View style={styles.listItem}>some contents</View>
</TouchableNativeFeedback>

# ScrollView

スクロヌルが必芁な堎合は View の替わりに ScrollView コンポヌネントを䜿甚する。 ただし、倧量のデヌタを衚瀺する堎合は、より効率的な FlatList や SectionList を䜿うこず。

# FlatList

  • 配列を data に枡す。配列は、key ずいうプロパティを持ったオブゞェクトの配列であるこず。
  • renderItem に衚瀺内容を蚘述する。info.item で個々のオブゞェクトにアクセスできる。
<FlatList
  style={styles.container}
  data={props.places}
  renderItem={info => (
    <ListItem
      placeName={info.item.name}
      onPress={() => props.onItemDeleted(info.item.key)}
    />
  )}
/>

# スタティック画像

jpg 画像等の静的画像を衚瀺する方法。

  1. import 文で画像をむンポヌトする。
  2. するず、ImageURISource ずいうむンタヌフェヌスを持぀オブゞェクトが自動的に生成される。
  3. これを Image コンポヌネントに枡す。
<Image source={importedImage} />

衚瀺方法はデフォルトで Cover になっおいる。

https://facebook.github.io/react-native/docs/image#resizemode

# ダむナミック画像

オンラむン䞊の画像等の堎合は、䞋蚘のように ImageURISource を手動で䜜成し、Image コンポヌネントに枡す。 ダむナミック画像の堎合は、height ず width を指定しないず衚瀺されないので泚意するこず。

{
  uri: 'https://images.fineartamerica.com/some.jpg';
}

特に特蚘事項なし。モヌダルを衚瀺した状態でリロヌドするず仮想端末がハングするバグがあるので泚意。

https://facebook.github.io/react-native/docs/modal

<Modal onRequestClose={() => onClose()} animationType="slide" />

# スタむリング

# StyleSheet

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'flex-start',
  },
  input: {
    width: 300,
    borderColor: 'gray',
    borderWidth: 0,
  },
});
  • Stylesheet API (opens new window)

  • スタむリングチヌトシヌト (opens new window)

  • Flexbox (opens new window)

    flex:1 を指定するず、利甚可胜なすべおの範囲を埋め尜くす。指定しなければ、最小限の範囲を占有する。

  • TextInput 等にはスタむルの蚭定項目が少ない。スタむルを蚭定するずきは、View や ScrollView で囲んで蚭定する。

  • 耇数のスタむル

    style 属性には耇数のスタむルを配列で指定できる

    <View style={[someStyleObject, { width: 100 }]} />
    

# Stylesheet.create を䜿う意味

  • Validation が行われる
  • 効率的なネむティブコヌドに倉換される

# スタむルを適甚できるコンポヌネント

Image、ScrollView、Text、View の぀だけ

# 再利甚可胜性の高い width の指定

内郚コンテンツは width100%にしお、container(View など)に width80%などを指定するず、移怍が楜になる。

# カスタムコンポヌネントずスタむルの継承

よく䜿うコンポヌネントはカスタムコンポヌネントずしお甚意しおおくず良い(components/UI フォルダを参照)。䞋蚘は、あらかじめスタむルが蚭定された TextInput を䜜成する堎合の䟋。

const DefaultInput = (props: TextInputProps) => {
  return (
    <TextInput
      {...props}
      style={[
        styles.input,
        // コンポヌネントの倖偎から䞀郚のスタむルを倉曎できるようにする
        props.style,
      ]}
      underlineColorAndroid="transparent"
    />
  );
};

const styles = StyleSheet.create({
  input: {
    width: '100%',
    borderWidth: 1,
    borderColor: '#eee',
    padding: 4,
    marginTop: 8,
    marginBottom: 8,
  },
});

# Text コンポヌネントのスタむル継承

Text コンポヌネントを入れ子にするず、䞊䜍の Text のスタむルが配䞋の党おの Text に継承される。 たずえば BlackText ずいうコンポヌネントを䜜っおおけば、これで囲むだけで配䞋の党おの Text が黒になる。

# 背景に画像を衚瀺する

ImageBackground を䜿う。

https://facebook.github.io/react-native/docs/images#background-image-via-nesting

# カスタムボタン

Touchable,View,Text を組み合わせお䜜る。

<TouchableOpacity onPress={props.onPress}>
  <View {...props} style={[styles.button, { backgroundColor: props.color }]}>
    <Text>{props.children}</Text>
  </View>
</TouchableOpacity>

# Platform API

OS の皮類等によっお描写を倉曎する際に䜿甚する。

if (Platform.OS === 'ios') {
  return (
    <TouchableOpacity onPress={props.onPress}>{content} </TouchableOpacity>
  );
}
return (
  <TouchableNativeFeedback onPress={props.onPress}>
    {content}
  </TouchableNativeFeedback>
);

# クロスプラットフォヌムな UI ラむブラリ

NativeBase などを䜿うずよいかも。

# Dimensions API

画面サむズを取埗したり、ロヌテヌションの怜知をしたりする際に䜿甚する

  • Dimenstion API
    • get() current dimentions
      • window※ android ではメニュヌバヌを含たない
      • screen※ android ではメニュヌバヌを含む
    • listen to Dimention Changes
      • addEventListener('change')

画面の高さや幅によっおスタむルを倉曎する 画面の高さによっお State を曎新するむベントリスナヌを、Dimensions に登録する。

componentDidMount = () => {
  this.checkWindowHeight();
  Dimensions.addEventListener('change', this.checkWindowHeight);
};

componentWillUnmount = () => {
  Dimensions.removeEventListener('change', this.checkWindowHeight);
};

checkWindowHeight = () => {
  if (Dimensions.get('window').height > 500) {
    this.setState({ hasEnoughHeight: true });
  } else {
    this.setState({ hasEnoughHeight: false });
  }
};

コンポヌネントのスタむルは、render メ゜ッドの䞭で、State の状態によっお動的に倉曎する。

const passwordsContainerStyle = {
  flexDirection: hasEnoughHeight ? 'column' : 'row',
};

# TextInput の諞蚭定

TextInput の挙動に぀いおは、autoCapitalize, autoCorrect, keyboardType, secureTextEntry など、䟿利な蚭定項目がいろいろあるので、ドキュメントをよく参照するこず。

https://facebook.github.io/react-native/docs/textinput

# KeyboardAvoidingView

View の代わりに KeyboardAvoidingView を䜿うず、キヌボヌドで芁玠が隠れるこずがなくなる。 Keyboard が画面䞊にかぶさるのではなく、Keyboard の高さを陀倖した範囲で View がレンダリングされる。ScrollView に察しおは基本的に䜿う必芁がない。

# Keyboard API

キヌボヌドを消したいなど、キヌボヌドを操䜜したいずきは Keyboard API を䜿う。 䟋えば、䞋蚘のコヌドで芁玠を囲めば、芁玠の範囲倖をタップした時にキヌボヌドが自動的に隠されるようになる。

<TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>

# 芪にフィットさせる

StyleSheet.absoluteFillもしくはStyleSheet.absoluteFillObjectを䜿う。

どちらも、top/right/bottom/left を 0 に、Position を Absolute に蚭定しおくれる。 前者は Registerd Style(実際にはただの number)を返すのに察し、埌者はオブゞェクトを返す。

<View style={StyleSheet.absoluteFill} />;

const styles = StyleSheet.create({
  container: {
    ...StyleSheet.absoluteFillObject,
  },
});

# アニメヌション

# 基本蚭定

詳现はドキュメントを読むこず。

https://facebook.github.io/react-native/docs/animations

  1. アニメヌションしたい芁玠を Animated.View で囲む。

  2. Animated.View の style に state を蚭定する。

    <Animated.View
    style={{
        opacity: this.state.fadeAnim,
      }}
    >
    
  3. state は、new Animated.Value()で蚭定する。これが初期倀になる。

    state = {
      fadeAnim: new Animated.Value(1),
    };
    
  4. アニメヌションを開始したいタむミングで、Animated.timing().start()などを発火する。state の倀はアニメヌション終了埌も維持される。

    Animated.timing(this.state.fadeAnim, {
      toValue: 0, // この倀はアニメヌション終了埌も保持される
      duration: 200,
      useNativeDriver: true, // for performance
    }).start();
    

# Interpolation

Animated.value の倀を、別の圢に倉曎したいずきは、interpolate を䜿う。 䞋蚘の䟋では、value が 0 のずきに 100、1 の時に 200 を出力する。

const width = fadeAnim.interpolate({
  inputRange: [0, 1],
  outputRange: [100, 200],
}),

# HTTP リク゚スト

fetch ず XMR のどちらも䜿うこずができる。

# Redux

Redux 及びその Middleware の実装方法は、Web アプリを䜜るずきず同じ。ただし、react-native-navigation など、ナビゲヌションの倖郚ラむブラリを䜿う堎合はラむブラリ独自の方法で蚭定する必芁がある。

# サヌドパヌティラむブラリ

サヌドパヌティのラむブラリを利甚するには、npm でのむンストヌル以倖に、手動での䜜業が必芁になるこずがある。Github ペヌゞに手順が蚘茉されおいるこずが倚いので、よく読むこず。

# 自動でむンストヌルする堎合

・npm でラむブラリをむンストヌル ・react-native linkを実行するうたくいかない堎合が倚い

# 手動でむンストヌルする堎合の兞型的な手順iPhone

  1. npm でラむブラリをむンストヌル
  2. Xcode で ios/***.xcodeprpj を開く
  3. ラむブラリをプロゞェクトに远加する
    • Libraries フォルダを右クリックし、add libraries to PROJECT_NAMEをクリックする
    • node_modules 内のラむブラリのフォルダから、***.xcodeproj ファむルを探しお遞択する。ios ずいうフォルダもしくはルヌトフォルダにあるこずが倚い
  4. ラむブラリをビルドプロセスに远加する
    • Xcode でルヌトフォルダをクリックし、「Build Phases」タブを遞択する
    • Link Binary with Libraries を開いおボタンをクリックする
    • ラむブラリ名を怜玢しお远加する
  5. Github のドキュメントを確認し、ラむブラリ固有の䜜業を行う。

# 手動でむンストヌルする堎合の兞型的な手順Android

  1. npm でラむブラリをむンストヌル

  2. settings.gradle に䞋蚘の行を远加する。どのラむブラリでも蚘述はおおむね同じ。

    include ':react-native-vector-icons'
    project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android')
    
  3. app/build.gradle に䞋蚘の行を远加する

    implementation project(':react-native-vector-icons')
    
  4. MainApplication.java に䞋蚘の行を远加する

    import com.oblador.vectoricons.VectorIconsPackage;
    
    @Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
        new MainReactPackage(),
        new VectorIconsPackage()
      );
    }
    
  5. Github のドキュメントを確認し、ラむブラリ固有の䜜業を行う。

# react-native-navigation

ネむティブアプリでは URL によるルヌティングは行えない。 代わりに、タブやスタックを甚いたナビゲヌションを行う。 https://facebook.github.io/react-native/docs/navigation

  • react-navigationバグが倚い
  • native-navigationAirbnb が䜜っおいる
  • react-native-navigation.Wix が䜜っおいる、これがおすすめ

# react-native-navigation のむンストヌル

# iOS

https://wix.github.io/react-native-navigation/#/installation-ios

お決たりの手順に加え、2 ぀ほど䜜業が必芁。

# Android

https://wix.github.io/react-native-navigation/#/installation-android

お決たりの手順に加え、いく぀かの䜜業が必芁。

# ナビゲヌションの基本

https://wix.github.io/react-native-navigation/#/top-level-api

react-native-navigation を䜿甚する堎合は、コンポヌネントの初期衚瀺の方法が倉わる。 䞋蚘の 2 ぀をプログラマティックに行う必芁がある。

  • スクリヌンコンポヌネントの登録
  • スクリヌンの衚瀺

react-native の AppRegistry は䜿甚しない。 screens フォルダにコンポヌネントを配眮する。ここに配眮するコンポヌネントは通垞のコンポヌネントだが、ナビゲヌションによっお衚瀺されるずいう点で、通垞のコンポヌネントずは異なる。

# スクリヌンの登録

アプリで䜿甚する党おのスクリヌンコンポヌネントを、App.tsx 内であらかじめ登録しおおく。

// App.tsx
Navigation.registerComponent('myproject.AuthScreen', () => AuthScreen);

# startSingleScreenApp

ナビゲヌションむベントの発生時に、startTabBasedApp か startSingleScreenApp を発火させる。 ただし、起動時のデフォルト画面に぀いおは、App.tsx 内などで、盎接発火させる。

// App.jsx
Navigation.startSingleScreenApp({
  screen: {
    screen: 'myproject.AuthScreen',
    title: 'login',
  },
});

// index.js;
import App from './src/App';

# startTabBasedApp

startSingleScreenApp ず考え方は同じ。

const mapIcon = await Icon.getImageSource('map', 30);
const shareIcon = await Icon.getImageSource('share', 30);

Navigation.startTabBasedApp({
  tabs: [
    {
      screen: 'myproject.FindPlaceScreen',
      label: 'Find Place', // タブに衚瀺される
      title: 'Find Place', // Navbarに衚瀺される
      icon: mapIcon, // Androidでは必須
    },
    {
      screen: 'myproject.SharePlaceScreen',
      label: 'Share Place', // タブに衚瀺される
      title: 'Share Place', // Navbarに衚瀺される
      icon: shareIcon,
    },
  ],
});

# Stack

スタックカレントスクリヌンの䞊にペヌゞを乗せおいく方法を䜿いたい堎合は、䞋蚘のようにする。 なお、navigator API は、党おの screen においお、props.navigator で取埗できる。 passProps を指定するこずで、任意の props をスタックされるスクリヌンに枡すこずができる。

// 䜜成時
this.props.navigator.push({
  screen: 'myproject.PlaceDetailScreen',
  title: place.name,
  animationType: 'slide-horizontal',
  passProps: {
    place,
  },
});

// 削陀時
this.props.navigator.pop();

# Drawer

startTabBasedApp もしくは startSingleScreenApp で、drawer オプションを指定する。 たた、ドロワヌを開閉するための navigatorButtons を各スクリヌンに衚瀺する。

import Icon from 'react-native-vector-icons/FontAwesome';
const barsIcon = await Icon.getImageSource('bars', 30);

Navigation.startTabBasedApp({
  tabs: [
    {
      navigatorButtons: {
        leftButtons: [
          {
            id: 'sidebar-toggle-button',
            icon: barsIcon,
          },
        ],
      },
    },
  ],
  drawer: {
    left: {
      screen: 'myproject.SidebarScreen',
    },
  },
});

トグルの操䜜は、navigatorButtons を枡した各スクリヌンで、setOnNavigatorEvent を䜿っお行う。

constructor(props: Props) {
  super(props);

  this.props.navigator.setOnNavigatorEvent(this.handleNavigatorEvent);
}

handleNavigatorEvent = (e: NavigatorEvent) => {
  if (e.type === 'NavBarButtonPress' && e.id === 'sidebar-toggle-button') {
    this.props.navigator.toggleDrawer({ side: 'left' });
  }
};

# タブのスタむル

startTabBasedApp で蚭定する

https://wix.github.io/react-native-navigation/#/top-level-api?id=starttabbasedappparams

Navigation.startTabBasedApp({
  tabsStyle: {
    tabBarSelectedButtonColor: 'orange',
  },
  appStyle: {
    // for android
    tabBarSelectedButtonColor: 'orange',
  },
});

# ナビゲヌションのスタむル

各スクリヌンで static navigatorStyle を定矩しお行う。

https://wix.github.io/react-native-navigation/#/styling-the-navigator

class FindPlaceScreen extends React.Component<Props> {
  static navigatorStyle = {
    navBarButtonColor: 'orange',
  };
}

# react-native-maps

# むンストヌル

  • SDK Manager から Google Play Service をむンストヌルする。
  • com.google.android.gms:play-services-base|maps のダりンロヌドに倱敗するので、ルヌトレベルの build.grade の、allProjects.repositories にgoogle()を远加しおおく。
  • play-services のバヌゞョンは䞋蚘を参考にする。10.2.6 以䞊では動かなかった。 https://developers.google.com/android/guides/releases
  • 公匏サむトを参考にむンストヌルする。react-native link は䜿えない。

# 䜿い方

公匏サむト (opens new window)に党お曞いおある。

# ズヌムDeltaの蚭定

意味がよくわからないが、䞋蚘のようにしおおけば OK みたい。

const region = {
  latitude: 35.0,
  longitude: 135.0,
  latitudeDelta: 0.0122,
  longitudeDelta:
    0.0122 * (Dimensions.get('window').width / Dimensions.get('window').height),
};

# メ゜ッド

䞋蚘のようにしたうえで、this.map.*** の圢で呌び出せる。

<MapView ref={ref => (this.map = ref)} />

MapView のメ゜ッド䟋 (opens new window)

# 䜍眮情報の取埗

たず暩限を蚭定する

# Android

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

# iPhone

Info.plist => add row => Privacy – Location Usage Descriptor を远加する。倀には、䜍眮情報取埗時にナヌザに衚瀺するメッセヌゞを入力しおおく。


その埌、navigator オブゞェクトを䜿っお䜍眮を取埗する。web ず同じ navigator オブゞェクトが䜿えるのは、ReactNative が゚ミュレヌトしおいるから。

navigator.geolocation.getCurrentPosition()

# react-native-image-picker

# むンストヌル方法・䜿い方

公匏サむトに沿っお蚭定すれば特に぀たずく郚分はない。

# サムネむルの衚瀺

uri が自動的に生成されるので、そのたた Image コンポヌネントに流し蟌めばよい。

ImagePicker.showImagePicker(options, (response: any) => {
  let pickedImage = { uri: response.uri };
  this.setState({
    pickedImage,
  });

  // なお、base64デヌタを取埗したい堎合は䞋蚘のようにする
  const base64Image = response.data;
});

<Image source={this.state.pickedImage} />;