【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
This component will automatically adjust its height, position, or bottom padding based on the keyboard height to remain visible while the virtual keyboard is di...

画面全体を囲っているタグにこの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で覚えていくしかないですね!

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

コメント