ReactとReact Nativeの共通点と相違点

はじめに

React Nativeは、Facebook(現Meta)によって開発されたクロスプラットフォームのモバイルアプリ開発フレームワークです。Reactをベースに構築されているため、Reactエンジニアにとっては親しみやすい一方で、React Native特有の機能や制約も存在します。

この記事では、普段ReactでWebアプリケーションを開発しているエンジニアの視点から、ReactとReact Nativeの共通点や違いを掘り下げて解説します。

共通点

まずは、ReactとReact Nativeの共通点について確認しましょう。

先に言ってしまうと、基本的な開発手法はほぼ同じです。普通にReactでWebアプリを作る感覚でモバイルアプリを作れます。

1. コンポーネントベースのアーキテクチャ

ReactとReact Nativeはどちらもコンポーネントベースのアーキテクチャを採用しています。これはUIを小さな部品(コンポーネント)に分割し、再利用可能で独立した単位として設計する思想です。これにより、コードの再利用性とメンテナンス性が向上します。

2. JSXによるコード記述

ReactもReact Nativeも、JavaScript拡張であるJSXを用いてUIを構築します。JSXを使うことで、JavaScriptのコード内にHTMLライクな構文でUIの記述ができるため、直感的にコンポーネントを作成できます。

3. 状態管理とPropsの使用

両者とも、状態(State)とプロパティ(Props)を使用して、動的なUIを管理します。useStateやuseEffectなどのReact HooksもReact Nativeで使用でき、コンポーネントのライフサイクルや状態を簡単に管理できます。

ReactとReact Nativeの違い

次に、ReactとReact Nativeの主な違いについて解説します。

プラットフォームの違いといった当たり前の違いは省いて、「全然Reactと違うやん」と思った箇所のみ紹介します。

1. UIコンポーネント

Reactでは、HTML要素(`<div>, <span>, <img>`など)を使用してUIを構築しますが、React NativeではこれらのHTML要素の代わりにネイティブUIコンポーネントが用いられます。

【React (Web)】

```tsx

const App = () => {

  return (

    <div style={{ textAlign: 'center' }}>

      <h1>Hello, Web!</h1>

    </div>

  );

};

```

【React Native (モバイル)】

```tsx

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

const App = () => {

  return (

    <View style={{ alignItems: 'center' }}>

      <Text style={{ fontSize: 24 }}>Hello, Mobile!</Text>

    </View>

  );

};

```

2. スタイリング方法

React Nativeでは、CSSを直接使用できません。React NativeがWebブラウザ上で動作するのではなく、モバイルデバイス上でネイティブに動作するアプリケーションを生成するためです。React NativeにおけるスタイリングはStyleSheet APIを利用したJavaScriptオブジェクトで行います。

```tsx

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

const styles = StyleSheet.create({

  container: {

    flex: 1,

    justifyContent: 'center',

    alignItems: 'center',

  },

});

```

また、以下のようなWeb特有のCSSプロパティが利用不可なので、代替の方法を考える必要があります。

  • :hoverなどの擬似クラスと擬似要素
  • グリッドレイアウト(display: grid)
  • position: fixed
  • float
  • calc

<参考>以下の記事にもっと詳しく書いてあるので、ぜひご参考ください。https://zenn.dev/cureapp/articles/d182e76ca1ea1c
https://qiita.com/nitaking/items/52ca6c23ba7c6c171d0e

3. デバイス対応とレイアウト設計

React Nativeはモバイルデバイス向けに設計されているため、デバイスの解像度や画面サイズに応じたレイアウトの適応が求められます。特に以下のようなモバイル特有の設計テクニックが必要です。

【解像度とピクセル密度への対応】

モバイルでは多様なデバイス解像度が存在するため、デザインの一貫性を保つために、以下のテクニックを活用します。

  • Dimensions API:デバイスの画面サイズを取得し、画面ごとにレイアウトを動的に調整
  • useWindowDimensions Hook:リアルタイムに画面サイズを取得し、レスポンシブなレイアウトを構築
```tsx

import { Dimensions, View, Text } from 'react-native';

const { width, height } = Dimensions.get('window');

const ResponsiveComponent = () => (

  <View style={{ width: width * 0.8, height: height * 0.3, backgroundColor: 'lightblue' }}>

    <Text style={{ textAlign: 'center', marginTop: 10 }}>Responsive Box</Text>

  </View>

);

```

【Flexboxによるレイアウト】

React Nativeでは、レイアウトの基本としてFlexboxを使用します。Webと同様の概念ですが、デフォルトのflexDirectionがcolumnになるなどの違いがあります。

```tsx

<View style={{ flex: 1, flexDirection: 'column', justifyContent: 'center' }}>

  <View style={{ height: 50, backgroundColor: 'powderblue' }} />

  <View style={{ height: 50, backgroundColor: 'skyblue' }} />

  <View style={{ height: 50, backgroundColor: 'steelblue' }} />

</View>

```

<参考> https://reactnative.dev/docs/flexbox

4. アニメーション

React NativeではAnimated APIを使い、アニメーションを実現します。複雑なアニメーションやジェスチャー操作が必要な場合は、react-native-reanimatedやreact-native-gesture-handlerなどのライブラリを使用します。

  • Animated API:JavaScriptのみで手軽にアニメーションを制御
  • react-native-reanimated:ネイティブコードで効率的にアニメーションを制御し、パフォーマンスを向上
```tsx

import React, { useRef, useEffect } from 'react';

import { Animated, View, Button } from 'react-native';

const FadeInView = () => {

  const fadeAnim = useRef(new Animated.Value(0)).current;

  const fadeIn = () => {

    Animated.timing(fadeAnim, {

      toValue: 1,

      duration: 500,

      useNativeDriver: true,

    }).start();

  };

  return (

    <View style={{ alignItems: 'center', marginTop: 50 }}>

      <Button title="Fade In" onPress={fadeIn} />

      <Animated.View style={{ opacity: fadeAnim, height: 100, width: 100, backgroundColor: 'tomato' }} />

    </View>

  );

};

export default FadeInView;

```

5. プラットフォーム固有のカスタマイズ

React Nativeでは、Platform APIを利用して、iOSとAndroidで異なる処理を実装可能です。たとえば、UIのデザインやハードウェアの違いに応じて、異なるコードを実行できます。

```tsx

import { Platform, StyleSheet } from 'react-native';

const styles = StyleSheet.create({

  container: {

    paddingTop: Platform.OS === 'ios' ? 20 : 0,

  },

});

```

6. リストとスクロールの実装

React Nativeでは、リスト表示やスクロール機能を実装する際に、FlatListやScrollViewといった専用のコンポーネントを使用します。これらはReact(Web)での`<ul>, <ol>, <div>`のスクロールとは異なる点が多く、パフォーマンスの最適化が重要です。

ScrollViewとFlatListの使い分け

  • ScrollView:表示するデータ量が少なく、コンテンツが静的である場合。
  • FlatList:大量のデータや動的なリストを表示する場合。

【ScrollView】

ScrollViewはスクロール可能なコンテナで、子要素をすべて一度にレンダリングします。少量のデータを表示する場合に適しています。注意として、大量のデータを表示する場合、すべての要素を一度にレンダリングするため、メモリ使用量が増加し、アプリのパフォーマンスが低下します。転職アプリ開発案件にて、求人が300件ある求人一覧画面でScrollViewを使った結果、全ての操作に15秒くらいかかりました。

```tsx

import { ScrollView, Text } from 'react-native';

const MyScrollView = () => (

  <ScrollView>

    {Array.from({ length: 20 }, (_, i) => (

      <Text key={i}>Item {i + 1}</Text>

    ))}

  </ScrollView>

);

```

【FlatList】

FlatListは大量のデータを効率的に表示するためのコンポーネントで、必要な要素のみをレンダリングします(仮想化)。リスト表示には基本的にFlatListを使用します。先ほど紹介した求人一覧画面でも、ScrollViewからこちらに変更したところだいぶ軽くなりました。

```tsx

import { FlatList, Text } from 'react-native';

const data = Array.from({ length: 1000 }, (_, i) => ({ key: i.toString(), title: `Item ${i + 1}` }));

const MyFlatList = () => (

  <FlatList

    data={data}

    renderItem={({ item }) => <Text>{item.title}</Text>}

    keyExtractor={(item) => item.key}

  />

);

```

まとめ

ReactとReact Nativeは、UIの構築方法やコードの再利用性、状態管理の方法など多くの共通点を持つ一方で、Webとモバイルのプラットフォームに対応したアーキテクチャやAPI、ツールなどが異なります。Reactの知識があるとReact Nativeも比較的容易に学べますが、モバイル特有のUIやデバイス機能の理解が必要となります。

React Nativeを使った開発をご検討の際は、ぜひご相談ください!