Flutter, React Native(Expo), Xamarin.Formsで別ファイルに引数を渡す場合の実装を比べる

[前に書いた記事](https://qiita.com/ito-kenichi/items/1c0d9ec464e4a82e080d)の後で、「別ファイルに引数ってどうやって渡すんだろう？」って思ったので、記事にしてみました。
今回はImageを別ファイルに切り出して、そのImageで表示する画像のURLを引数として渡す場合を例にしました。

調べた時に「要点となる実装部分だけの記載」という記事が多くて、初心者にとっては実装する時に「このコードはどこに追加(置き換え)するんだろうか？」って思ったので、FlutterとReact Native(expo)はコピペで動作するように記載しました。Xamarin.Formsはコピペの後でnamespaceを書き換えてください。
今回取り上げることは、ページやタブを別ファイルに切り出した時やリファクタリングを行う時にも役にたつと思います。。（たぶん）

# 留意事項
## その１
「こう実装すればこう動く、ってことが分かれば、それでOK！」を方針に実装を進めた個人開発の内容を記載しましたので、「なぜその実装が必要なのか？」や「なぜその実装で動くのか？」は分かってない部分多数です。。。 :bow:

## その２
筆者は実戦経験が乏しい（というより、アプリ開発は個人開発を除いて、現場での開発が未経験。。）、なので、ご指摘は「ここは、こうした方が良いよ:wink:」くらいのノリでお願いします。:pray::pray::pray:

## その３
「HelloWorldはできたけど、他にはこんなことできたら嬉しいな〜」って思っていた時のことを思い出して書きました。そのため、強々エンジニアや超人エンジニアの方々はこのページを参考にしない方が良いと思います。:expressionless::sleepy: :cold_sweat:

※iOSとAndroidのバージョン
![iOS-13.3](https://img.shields.io/badge/iOS-13.3-brightgreen)![Android-29(API Level)](https://img.shields.io/badge/Android-29(API Level)-brightgreen)

# Flutter

以下の記事を参考に、Flutterで引数を渡す実装を行いました。
参照記事：https://stackoverflow.com/questions/53861302/passing-data-between-screens-in-flutter

## 概要

- 引数をもらう方(ImageWidget.dart)：@reqiureをつけて引数名を指定
- 引数を渡す方(main.dart)：もらう側が設定した引数名と値を指定

## 実装

![Flutter-1.20.3](https://img.shields.io/badge/Flutter-1.20.3-brightgreen)

```dart:ImageWidget.dart
import 'package:flutter/material.dart';

class ContentsImage extends StatelessWidget {
  final String imagePath;
  // imagePathという引数を(@requireをつけて)設定する
  ContentsImage({Key key, @required this.imagePath}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Center(
        child: InteractiveViewer(
          boundaryMargin: EdgeInsets.all(20.0),
          minScale: 0.1,
          maxScale: 3.0,
          child: Image.network(
            imagePath,
            width: 500,
            height: 500,
          ),
        ),
      ),
    );
  }
}
```

```dart:main.dart
import 'package:flutter/material.dart';
import 'ImageWidget.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        // imagePathという引数名に画像のURLを設定する
        child: ContentsImage(imagePath:'https://picsum.photos/250?image=9'),
      ),
    );
  }
}
```

# React Native(Expo)

以下の記事を参考に、React Native(Expo)で引数を渡す実装を行いました。
参照記事：https://stackoverflow.com/questions/42859156/how-to-access-one-component-state-in-another-component-if-those-two-component-de/42859700

## 概要

- 引数をもらう方(DisplayImage.js)：this.props[$引数名]を指定
    - 引数名がhogeの場合：this.props.hoge
- 引数を渡す方(App.js)：もらう側が設定した引数名と値を指定

## 実装
![React Native cli-2.0.1](https://img.shields.io/badge/React Native cli-2.0.1-brightgreen)![Expo-3.23.3](https://img.shields.io/badge/Expo-3.23.3-brightgreen)

```javascript:DisplayImage.js
import React from "react";
import { StyleSheet, View, Image } from 'react-native';

export default class DisplayImage extends React.Component{

  render() {
    return (
      <View style={styles.Container}>
        <Image
          style={{ width: 500, height: 500 }}
          // imagePathに画像のURLが格納される
          source={{ uri: this.props.imagePath }}
        />
      </View>
    );
  }
};

const styles = StyleSheet.create({
    Container: {
      width:  500,
      height: 500,
      margin: 20,
    }
});

```

```javascript:App.js
import React from 'react';
import { StyleSheet, View } from 'react-native';
import DisplayImage from "./DisplayImage"

export default class App extends React.Component {

  constructor(props) {
    super(props);
  }

  render() {
    return (
      <View style={styles.container}>
        <DisplayImage
          // DisplayImageファイル側で指定したimagePathという引数に画像のURLを設定する
          imagePath={'https://picsum.photos/250?image=9'}
        />
      </View>
    );
    }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

```

# Xamarin.Forms

以下の記事を参考に、Xamarin.Formsで引数を渡す実装を行いました。
参照記事：https://stackoverflow.com/questions/53353374/xamarin-pass-data-to-another-page

## 概要

コードビハインドでの実装を行う場合です。xamlファイルの実装は、、、調べ中です。
- 引数をもらう方(DisplayImage.xaml.cs)：コンストラクタに引数を設定する
- 引数を渡す方(MainPage.xaml.cs)：コードビハインドでインスタンス引数に設定する

## 実装
![Xamarin.Forms-4.6.0.1141](https://img.shields.io/badge/Xamarin.Forms-4.6.0.1141-brightgreen)

```xml:DisplayImage.xaml
<?xml version="1.0" encoding="UTF-8"?>
<Image
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:d="http://xamarin.com/schemas/2014/forms/design"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    x:Class="xamarin.forms_project.DisplayImage"
    x:Name="image"
    HeightRequest="500"
    WidthRequest="500"
    >
</Image>
```

```C#:DisplayImage.xaml.cs
using System;
using Xamarin.Forms;

namespace xamarin.forms_project
{
    public partial class DisplayImage : Image
    {
        //imagePathという引数のついたコンストラクタを生成
        //今回のケースでは引数なしコンストラクタは不要です
        public DisplayImage(string imagePath)
        {
            InitializeComponent();
            image.Source = ImageSource.FromUri(new Uri(imagePath));
        }
    }
}
```
```xml:MainPage.xaml
<?xml version="1.0" encoding="utf-8"?>
<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="xamarin.forms_project.MainPage">
    <StackLayout x:Name="layout">
    </StackLayout>
</ContentPage>
```

```C#:MainPage.xaml.cs
using Xamarin.Forms;

namespace xamarin.forms_project
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
            // インスタンスに画像のURLを設定
            var image = new DisplayImage("https://picsum.photos/250?image=9");
            // 生成したDisplayImageの画像をStackLayoutに追加
            layout.Children.Add(image);
        }
    }
}
```