プラットフォーム固有の実装パターン
React Native for Webが独立したライブラリであるからこそ、すべてのコンポーネントが完全に互換性を持つわけではありません。プラットフォーム固有の機能を使い分けるための実装パターンを見ていきましょう。
Platform.OSによる条件分岐
最も基本的な方法は、Platform.OSによる条件分岐です(リスト1)。
import { Platform, View, Text } from 'react-native';
export default function PlatformInfo() {
return (
<View>
<Text>現在のプラットフォーム: {Platform.OS}</Text>
{Platform.OS === 'web' ? (
<Text>Webブラウザで実行中です</Text>
) : (
<Text>モバイルアプリで実行中です</Text>
)}
</View>
);
}
Platform.OSは、iOS、Android、Webそれぞれで異なる値('ios'、'android'、'web')を返します。
Platform.selectによる値の切り替え
複数のプラットフォーム向けに値を切り替える場合は、Platform.selectを使うとより簡潔に書けます(リスト2)。
import { Platform, StyleSheet } from 'react-native';
const styles = StyleSheet.create({
container: {
padding: Platform.select({
web: 20,
ios: 15,
android: 10,
}),
fontFamily: Platform.select({
web: 'system-ui, -apple-system, sans-serif',
default: 'System', // iOS/Android共通
}),
},
});
Web専用ファイルによる実装分割
より大きな実装の違いがある場合は、.web.tsx拡張子を使用してWeb専用の実装を提供できます。この拡張子のファイル内では、<div>などのDOM要素を直接利用できます。
これは、.android.tsxや.ios.tsxの拡張子をつけることでプラットフォームごとにピックアップされるファイルを切り替えられる、React Native本来の仕組みに則ったものです(リスト3)。
components/ ├── FileUploader.tsx # モバイル向け基本実装(expo-image-picker使用) ├── FileUploader.web.tsx # Web専用(HTML input[type="file"]使用) ├── NotificationBanner.tsx # Web向け基本実装(DOM操作使用) └── NotificationBanner.native.tsx # モバイル専用(expo-notifications使用)
この例では、FileUploaderは「モバイル+Web専用」、NotificationBannerは「Web+モバイル専用」の組み合わせになっています。
Webビルド時には.web.tsxが、iOS/Androidビルド時には.native.tsxが優先的に読み込まれ、該当するファイルがなければ無印(.tsx)が使用されます。この仕組みにより、プラットフォームごとに最適化された実装を透過的に切り替えることができます。
