【ReactNative】Reactとの違い

ReactNativeを初めて触ってみて、Reactとの違いについて気づいた点をサクッとまとまています。

タグの違い

Core Components and Native Components · React Native
React Native lets you compose app interfaces using Native Components. Conveniently, it comes with a set of these components for you to get started with right no...

div等のタグが異なります。

divの代替はViewになりますが、画面からはみ出すことが想定される場合はScrollViewというタグを使用することで、scrollのスタイルを当てることができます。

CSSスタイルの当て方

StyleSheetを使用します。

Styleの定義の仕方はReactよりも少し追加で記述が必要になります。

colorを指定する場合で比較しましょう。

React
function Hello() {
  return (
    <View>
      <Text style={style}>
        Hello
      </Text>
    </View>
  );
}

const style = {
    color: '#ffffff',
};
ReactNative

これに対しReactNativeでは

function Hello() {
  return (
    <View>
      <Text style={styles.text}>
        Hello
      </Text>
    </View>
  );
}

const styles = StyleSheet.create({
  text: {
    color: '#ffffff',
  },
});

しかし、これは何もReactNativeに限った書き方でなく、従来のReactの書き方で書くことも可能。

Styleの縦横が逆

例えば、以下のStyleを当てたときに縦横が逆になります。

ReactReactNative
aliginItems縦方向横方向
justifyContent横方向縦方向

padding等の方向指定

通常、paddingの方向指定はtopやbottom, left, rightで行いますが、

ReactNativeでは、縦方向はpaddingVertical, 横方向はpaddingHorizontalを使用します。

shadow

webアプリでは、こんなふうに指定できるshadowですが、モバイルアプリでは書き方が全く異なります。

box-shadow: 10px 5px 5px red;

ReactNativeの場合

且つ、iOSの場合

shadowはiOSとAndroidで書き方が異なるんですね。

    shadowColor: '#000000',
    shadowOffset: { width: 0, height: 8 },
    shadowOpacity: 0.25,
    shadowRadius: 8,

Androidの場合

一行で指定ができます。

    elevation: 8,

これは、Material DesignのElevationという概念を使っています。

Material Design
Build beautiful, usable products faster. Material Design is an adaptable system—backed by open-source code—that helps teams build high quality digital experienc...

elevationを8とすることで、位置が8dpにあることを意味しており、その影が表現されるというわけです。

キーボード表示

webアプリと違ってスマホアプリは編集時にキーボードが表示されます。

キーボードが表示されたときには、画面をリサイズしたいのでKeyboardAvoidingView というものを使用します。

KeyboardAvoidingView · React Native
It is a component to solve the common problem of views that need to move out of the way of the virtual keyboard. It can automatically adjust either its height, ...

画面全体を囲っているタグにこのKeyboardAvoidingViewを使用します。

そしてbehaiverにheightを指定

import { View, StyleSheet, TextInput, KeyboardAvoidingView } from 'react-native';

<KeyboardAvoidingView behavior="height'}>
  ここに画面の要素を記述
</KeyboardAvoidingView>

クリックイベント

ボタンにクリックイベントを設ける方法についてです。

実現方法は

  • propsTypesにonPress: funcを設定する
  • TouchableOpacityを使用する
import { TouchableOpacity } from 'react-native';
import { func } from 'prop-types'

CircleButton.propsTypes = {
  onPress: func
}

CircleButton.defaultProps = {
 onPress: null
}

funcはfunctionの意味で関数を意味しています。

Viewタグではクリックイベントを設けることができないので、TouchableOpacityというタグを使います。

TouchableOpacity · React Native
If you're looking for a more extensive and future-proof way to handle touch-based input, check out the Pressable API.

これは、Viewにtouchを適用させるためのwrapperです。

ここで使うonPressなどのpropsは、TouchableWithoutFeedbackを継承していますのでそちらのドキュメントを見てみます。

TouchableWithoutFeedback · React Native
If you're looking for a more extensive and future-proof way to handle touch-based input, check out the Pressable API.

onPressの説明がありますね。

どのように使うのかが確認できたので、TouchableOpacityを使っていきます。

TouchableOpacity適用前

<View style={[styles.circleButton, style]}>
  <Feather name={name} size={32} color="white" />
</View>

TouchableOpacity適用後

<TouchableOpacity style={[styles.circleButton, style]} onPress={onPress}>
  <Feather name={name} size={32} color="white" />
</TouchableOpacity>

chableOpacityタグで囲って、onPressを追加しました。

Alertの表示

クリックイベントが機能しているかの確認には、まずはじめにalertを表示させるのが鉄板ですよね。

React Nativeでのalertの表示方法がこちらになります。

import { Alert } from 'react-native';

export default function MemoEditScreen() {
  return (
      <CircleButton name="check" onPress={() => { Alert.alert('押したよ'); }} />
  );
}

onPressのpropsをCircleButtonに渡しています。

React Navigation

ルーティングも異なります。

https://reactnavigation.org/docs/getting-started

ライブラリをinstallします。

$ npm install @react-navigation/native

versionを指定する場合は
$ npm install @react-navigation/native@6.0.6

次に依存関係をinstall

expo installで実行することで、現在使用しているSDKに合わせて適切な依存関係をinstallしてくれます。

ここまでinstallが完了すると、Hello React Navigation に進むことができます。

stackをinstallします。

https://reactnavigation.org/docs/hello-react-navigation#installing-the-native-stack-navigator-library

画面遷移

画面遷移はnavigationを使って、以下のように指定します。

export default function LogInScreen(props) {
  const { navigation } = props;

  return (
    <Button
      label="Submit"
      onPress={() => { navigation.navigate('遷移先画面のname'); }}
    />
  )
}

戻るボタンとしたい場合は、onPress部を以下のように記述します。

onPress={() => { navigation.goBack(); }}

Screenでない要素の画面遷移

Screenのコンポーネントの画面遷移には上記のようにpropsでnavigationを渡せばよかったですが、

Screenでなく、要素に画面遷移を指定する場合はpropsでnavigationを渡すことができません。

そのため、そのような場合は以下の記述方法となります。

import { useNavigation } from '@react-navigation/native';

export default function MemoList() {
  const navigation = useNavigation();
  return (
    <TouchableOpacity
      onPress={() => { navigation.navigate('MemoDetail'); }}
    >
  以下省略

Stack

ログイン後に「戻る」ボタンを消す方法についてです。ログインした最初に表示される画面で「戻る」ボタンが表示されていたらおかしいですよね。

stackにはページの遷移の履歴を蓄積されています。

そのため、その履歴を削除すれば、戻るボタンが表示されなくすることができます。

上記で扱ったnavigationの書き方を変更します。

履歴が削除されない記述の仕方

onPress={() => { navigation.navigate('MemoList'); }}

履歴が削除される記述の仕方

resetを使用します。

onPress={() => {
  navigation.reset({
    index: 0,
    routes: [{ name: 'MemoList' }],
  });
}}

reset により、routes で指定したnameで上書きがされ、indexの0番目を表示するという指示になり履歴を無くすことができます。

まとめ

ReactとReactNativeの違いは、こちらにまとめたものはほんの一部に過ぎないと思います。

もう少し似ているかなと思っていたんですが、想定以上に異なっていました。

NativeはNativeで覚えていくしかないですね!

以上、お読みいただきありがとうございました。

コメント