FC2ブログ

スマフォのアプリを作りたい(7):React Nativeのテンプレートを読む

   プログラミング [2020/01/23]
前回、ReactのJavaScriptの記述の文法?・・・というか書き方についてちょっとだけお勉強してみました。
で、いよいよReact Nativeのコードサンプルについて見てみます。
でも、前回のお勉強だけでは足りませんでした。
見れば見るほど分からないことだらけで、また発散しまくってます。

ここで、前回のお勉強経緯の説明でも流してきた用語についてちょっとだけ注釈しておきます。
ES6:ESはECMAScriptの略。ECMAはEuropean Manuufacturer Associationの略で国際標準規格。(頭に「欧」って付いてるけどね。)ECMAScriptはJavaScriptの標準規格。ES6はES2015のことで、2015年にリリースされた規格。


React-Nativeアプリ(テンプレート)のソース構成(一部)は、
 ・index.js   :エントリスクリプト
 ・app.json   :プロジェクト(プログラム名)を規定しているデータファイル
 ・App.js    :アプリの処理本体
 ・.flowconfig  :Flowによるチェック動作のパラメタ/オプション指定
 :

なんかが含まれているようです。
使われ方は、以下のボヤキの中に順次出て来たり来なかったり。


◆index.js
プロジェクト・フォルダ直下にあった、index.jsは以下の内容でした。
これが、このアプリのオオモトですよね。きっと。
----JSX:------------------------------------------
/**
* @format
*/

import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';

AppRegistry.registerComponent(appName, () => App);
--------------------------------------------------

最初のimportは、React Nativeのコードとしては必須の記述でしょう。たぶん。
「AppRegistryという名前のコンポーネントを使う」宣言ですね。
2番目は、このアプリ固有の処理コードを含むApp.js(入口コード)なので、至極当然。
3番目は、app.jsonは、以下の内容でした。
----JSON:-----------------------------------------
{
"name": "VTChat",
"displayName": "VTChat"
}
--------------------------------------------------

nameというキー(名前)に"VTChat"というバリュー(値:プロジェクト名)が割り当ててあります。
それをindex.js上では、appNameという名前で参照できるようにしてるんですね。
.jsonファイルをimportするだけで、中のデータを使えるということを今初めてしりました。
ただし、さるには.jsonが「XML的にデータ構造を階層化して記述できる形式/ファイル」くらいの認識しかありません。

でもって、react-nativeに含まれるAppRegistry.registerComponent()メソッドを呼び出してるところでこのファイルは終わりです。
AppRegistry.registerComponent()はこのアプリのエントリーポイントを指定するメソッドだそうです。
つまり、App.jsに含まれるAppというコンポーネントを呼び出すようにしてるんですね。
AppRegistry.registerComponent("アプリ名", () => コンポーネント名);

※App.jsを見ると「App」は関数として定義されている感じ。React Nativeでは「関数」と「コンポーネント」は同義?

話を戻します。index.jsはAppRegistry.registerComponent()以外は他に何もしてない。

つづいて・・・
◆App.jsの概要
※割と長かったので、全文を載せるのはやめときました。
(1)import
まずは、先頭のインポートです。
----JSX:------------------------------------------
import React from 'react';
import {省略} from 'react-native';
import {省略} from 'react-native/Libraries/NewAppScreen';
--------------------------------------------------

「省略」箇所は、使用されているコンポーネント名がカンマ区切りで列挙されてます。
先頭のimportは、おそらくReactのJavaScript記述で書いているコードなので必須でしょう。
2番目、3番目はReact-Nativeに含まれるコンポーネント:APIってことですね。


(2)const App : () => React$Node = () => {・・・}
----JSX:------------------------------------------
const App: () => React$Node = () => {
return (
<>
<StatusBar barStyle="dark-content" />



</>
);
};
--------------------------------------------------

とあるのですが、のっけから意味が分かりません。
「const App : () => React$Node = () => {」なんじゃこれは?

今までうっかり見過ごしてたが、constって?
→ES6で規定された変数型で、宣言後に書き換えられない変数を表す。
まあ想像は付いたけど、いつからJavaScriptにこんなのが?と思って調べた。
さるがいくらか知っているJavaScriptの仕様が如何に古いか知れちゃいますね。

その後のアロー関数式っぽい部分。
なぜ「App = () =>」じゃないのか?
オブジェクト要素にメソッドを定義する記述なのか・・・?
でも、これまでの認識からすると「const オブジェクト = {・・・, App : () => {・・・}, ・・・}」とかになるような気がするが、そうにもなってない。
では「App:」とは何なんだ?
その次のReact$Nodeってとこも・・・「$」ってなんだよ。
→上記の疑問をクリアにしたかったので文法的な説明を漁ってみたものの、ぴったりくる解説がすぐには見つけられなかった。

やっと探し当てたのが以下のサイトです。同じ疑問を抱いた方がいたんですねきっと。
★1:https://medium.com/codespace69/const-app-react-node-what-does-this-mean-b32f5b360839
「Flow」という新しい言葉が出てきました。
Flowは、JavaScript中のデータ型のエラー(不適切)をチェックするツールのようです。
★2:https://www.webprofessional.jp/writing-better-javascript-with-flow/

・Flowは、JavaScriptの変数型をチェックする静的解析ツール?のようなもの。
・Flowは文脈から型を推定することもするが、コード内で明示的に型を指定することもできるらしい。
 それが、「変数名:型指定」と表現されるらしい。型指定は(型)アノテーションと呼ばれている。
 ・・・JavaScriptで変数の型を気にするようになってたなんて。時の流れを感じます。
・型は独自なものを定義できるみたい。
React$Nodeは独自の型ってことで、react.js内で定義されているらしい。
・Flowでチェックさせたいソースの先頭コメントとして @flow と入れるんだそうです。
 ・・・ホンマや。App.jsの先頭のコメントの中に「@flow」と入っています。
 (「@format」とも書いてある。・・・不安。これもなんか意味があるんでしょうね。)

つまり★1の説明によると、「const App : () => React$Node」までがApp関数の型指定で、
その後の「= () => {・・・}」が関数の実体を表すようです。
React$Nodeは、リターン値のということになる。

でもホントけ?と思えたので、「Func : () => Return_Type」みたいなFlowのアノテーションの記述例がないか探しまくったが、結局探せなかった。
唯一「関数名 = (パラメタとその型指定) => リターン型」という記述の仕方の例を見つけたのみ。
なので、未だ半信半疑です。
それと、Appの前にあるconstとアノテーションで指定されるリターン型との関係性については「もやっ」のままです。
上記2点は、しばらく放置して次に進みます。


(3)const styles = StyleSheet.create(・・・)
App関数の下には、「const styles = StyleSheet.create(・・・)」があって、stylesというオブジェクト(CSS風?)を作成しているようです。
Reactだったら、スクリプト内でstyleを定義する(インラインスタイル)場合、例えば「const styleA = {属性名:値, ・・・};」と書けるそうです。
でもReact Nativeの場合は、「const styleA = StyleSheet.create({属性名:値, ・・・});」とすることが推奨されています。

(4)export default App;
「export default App;」とあるのは、Appという関数を外部から参照できるようにしているんですね。
export→importの関係はそれとして、defaultと指定した場合、import側が好きな名前を付けることができるらしい。import時にその名前を{}で囲む必要もなし。


◆App関数の中身
さ、こっからやっと本番ですね。
ざーっと見た感じは、<名前1 ・・・><名前2 ・・・/><名前3 ・・・/>・・・<名前1 /> ってなってます。
名前xは、頭が大文字だし、このApp.js内に定義されていないので、ReactかReact Nativeで提供しているコンポーネントってことでしょう。
そのコンポーネントのネストで、表示される(HTMLのタグ状の)ものがreturnされて、それが結果的に描画されるんだと思います。
現時点では、コンポーネントからの出力の形式は重要ではないので、各機能を調べていけば、何を出そうとしてるか分かると予想します。

あまり、使っている種類は多くはないので、一個一個の概要を以下に調べた順序のまま書きます。
正式には、本家さんのAPIリファレンスを参照してください。
https://facebook.github.io/react-native/docs/activityindicator


(1)<>(<React.Fragment>)
初っぱな大外が「<>・・・</>」となってます。
これは、「<React.Fragment>・・・</React.Fragment>」の省略形だそうで、
<React.Fragment>は、挟まれた範囲に含まれる<タグ>の並びに対して、「有って当然のタグ」を補う機能だそうです。
たとえば、「<td>1</td><td>あいさつ</td>」とだけ出力されるようになっていたら、
「<React.Fragment><td>1</td><td>あいさつ</td></React.Fragment>」とすれば、
最終的な出力は「<table><tr><td>1</td><td>あいさつ</td></tr></table>」とかになるんだって。
※色んなタグの種類が混在する並びになってても、それぞれ適切に補完されるんだろうか・・・今のところ不明です。

(2)<StatusBar />
アプリのステータスバーを制御するコンポーネントです。
以下のAndroidエミュレータ上での絵の一番上のグレーの部分が「<StatusBar barStyle="dark-content" />」一行で出せてるってことですよねきっと。
※すげー。

20191224_9.jpg


(3)<SafeAreaView>・・・</SafeAreaView>
表示エリア上にアプリの独自内容を描画するエリア(safe area)を作って(制御して)いるようです。
この間にネストされたコンポーネントでコンテンツを描画します。(SafeAreaViewはエリアを切っているだけで、描画内容は別のコンポーネントの記述を挟んで行うってことです。)


(4)<ScrollView>・・・</ScrollView>
表示エリア内に配置されて、挟んだコンポーネントの内容のスクロールを制御するようです。
パラメタが2つ指定されてます。contentInsetAdjustmentBehaviorは・・・リファレンスを参照してください。
styleについては、このファイル内の下に定義されているstyles(.scrollView)を参照しています。


(5)<Header />
注:
Headerを先の本家のサイトのAPIから探しても見つかりませんでした。
ぐぐってみたら、以下のサイトが引っ掛かりました。
https://react-native-elements.github.io/react-native-elements/docs/header.html
ただ、サイト左上に書いてあるバージョンが0.61ではない。
よくよく見ると「React Native Element」って書いてあります。なんですか?これは。
⇒React Native環境に追加できるフレームワークのようです。
追加でインストールが必要なようなことが書いてあるサイトもありました。
でもインストールした記憶はないので、このAPIではないみたいです。
紛らわしいのがあるので、要注意です。

参考までに、React Native Elementの<Header>だったら
「カレント・スクリーンに関連情報とアクション?を表示するナビゲーション・コンポーネント」だそうです。
パラメタで表示する標準コンポーネント?が選択できるようです。
カスタムな内容を表示したい場合は、オリジナルの<コンポーネント>を<Header>・・・</Header>で挟めばいいみたい。

<Header>は、react-native/Libraries/NewAppScreenからimportされてます。
リファレンスがないので、import元を見てみました。
パスは、「(プロジェクトフォルダ)\node_module\react-native\Libraries\NewAppScreen\」ではないかと思います。
NewAppScreenはフォルダでした。フォルダをimport元に指定すると、フォルダ中のindex.jsが使われるんですね。
そのinxex.js内でさらにimportされてたので、実際のHeaderコンポーネントのコードは、
「(プロジェクトフォルダ)\node_modules\react-native\Libraries\NewAppScreen\components\Header.js」のようです。
中身は、以下のようになってました。
----JSX:------------------------------------------

const Header = (): Node => (
<ImageBackground
accessibilityRole={'image'}
source={require('./logo.png')}
style={styles.background}
imageStyle={styles.logo}>
<Text style={styles.text}>Welcome to React</Text>
</ImageBackground>
);

--------------------------------------------------

<ImageBackground>と<Text>というコンポーネントが出てきましたね。
背景画像とその上に表示するテキストが指定されています。
実際の画面上の表示とも一致します。
各コンポーネントの機能については(9)(8)で改めて説明します。
元のApp.jsの続きに戻ります。


(6){global.HermesInternal == null ? null : (・・・)}
やっとJavaScriptっぽい?
まずは、global.HermesInternalという変数 ・・・何かの状態を表してそうです。
Hermes(エルメス)、およびHermesInternalについては本家の以下で説明されてました。
https://facebook.github.io/react-native/docs/hermes
Hermasは、Android用に最適化されたJavaScriptエンジンだそうです。
つまり、HermesInternalはHermesが使用可能かどうかを表していて、使える状態なら「:(・・・)」と記述されているかっこの中身が有効で、使えないのであればnull(なし)ってことでしょう。たぶん。


(7)<View>・・・</View>
UIを構築する基本的なコンポーネントだそうです。
「コンテナ」という表現をされており、View自体は「入れ物」だと思えばいいんでしょう。
styleとして、同ファイル内で定義されているstylesの指定が選択されています。
(例えば、最初のViewのスタイル指定(engine)では、「入れ物」の配置指定をabsolute(座標値の単位)として、右マージンを(right:)0にしてる感じ。)


(8)<Text>・・・</Text>
テキストを表示するためのコンポーネント。
<Text>と</Text>の間に記述されたテキストを表示します。
文字の属性はstyleで設定しています。

※global.HermesInternalがnullじゃないときに「Engine: Hermes」と表示することになっているようですが、エミュレータの画面上にはそのような表示はなかったので、この環境にHermesは組み込まれていないということですね。
サンプルApp.jsのその後では、「Step One・・・」、「See Your Changes・・・」、「Debu・・・」、「Learn More・・・」を表示している記述(<Viewt>&<Text>)が続いています。


(9)<ImageBackground>・・・</ImageBackground>
CSSでいうところのbackground-imageに相当する機能を提供するようです。
詳しくはわかりませんが、背景画像を指定するものです。
パラメタ(props)に関しては<Image>と同じ?らしく、そちらを参照するか、あるいはコンポーネントのコードを見るようにとあります。
(5)<Header />コンポーネントの例にあるように、背景画像に文字を重ねる場合は、<ImageBackground>と</ImageBackground>とで<Text>コンポーネントを挟めばいいんですね。


(10)<ReloadInstructions />、<DebugInstructions />
これらのコンポーネントのリファレンスはありません。
react-native/Libraries/NewAppScreenからimportされているので、ローカルなコンポーネントということですね。
おそらく、このテンプレートAppでは、React Nativeのチュートリアルを表示するようになっていて、エミュレータ/デバッガの制御/呼び出し操作にAndroidとiOSで違いがあるために、そこの交通整理を含めたコードになっているのではないかと思います。

ReloadInstructionsを例に、実際の中身を見てみましょう。
<ReloadInstructions />は、「(プロジェクトフォルダ)\node_modules\react-native\Libraries\NewAppScreen\components\ReloadInstructions.js」にあります。
----JSX:------------------------------------------

const ReloadInstructions: () => Node = Platform.select({
ios: () => (
<Text>
Press <Text style={styles.highlight}>Cmd + R</Text> in the simulator to
reload your app's code.
</Text>
),
default: () => (
<Text>
Double tap <Text style={styles.highlight}>R</Text> on your keyboard to
reload your app's code.
</Text>
),
});

--------------------------------------------------

予想通りでのようですが、
Platform.selectというメソッドを使って、スマフォがiOSかそれ以外かを区別し、出力するコンテキストを切り替えるようになっているみたいです。
ただし、Platformは、本家のサイトでは「モジュール」という呼び方になっていて、リファレンスのComponents/APIsのいずれにも含まれてませんでした。
なので使い方の詳細は、・・・以下のURLの説明で十分なのかどうか・・・不明です。
https://facebook.github.io/react-native/docs/platform-specific-code#platform-specific-extensions
実際のスクリプトを見れば分かるかなーと思って、「import ・・・ from 'react-native';」のルートファイルを探してみたのですが、現段階では??????です。

上記のサンプルのソースでは、表示するテキストを使い分けしてるだけのようなので、まずは「そういうもんだ」くらいで止めときます。


(11)<LearnMoreLinks />
最後に出てきたこのコンポーネントもreact-native/Libraries/NewAppScreenからimportされています。
実際にエミュレータ上で表示されている内容は盛りだくさんです。スクロールさせると出てきます。
20200123_1.jpg20200123_2.jpg
これら一式を出力している部分が「<LearnMoreLinks />」の1行のようです。
URLをブラウズする機能が含まれているらしく、表示している「The Basics ・・・」等の項目をクリックするとReact Native本家のサイトの該当ページがブラウザを使って表示されます。

コードの中身は、
----JSX:------------------------------------------

const links = [
{
title: 'The Basics',
link: 'https://facebook.github.io/react-native/docs/tutorial',
description: 'Explains a Hello World for React Native.',
},
{
title: 'Style',
link: 'https://facebook.github.io/react-native/docs/style',
description:
'Covers how to use the prop named style which controls the visuals.',
},



];

const LinkList = (): Node => (
<View style={styles.container}>
{links.map((item, index) => {
return (
<React.Fragment key={index}>
<View style={styles.separator} />
<TouchableOpacity
accessibilityRole={'button'}
onPress={() => openURLInBrowser(item.link)}
style={styles.linkContainer}>
<Text style={styles.link}>{item.title}</Text>
<Text style={styles.description}>{item.description}</Text>
</TouchableOpacity>
</React.Fragment>
);
})}
</View>
);

--------------------------------------------------

linksという連想配列を定義しています。要素項目は、[title:, link:, description:]となってます。
その配列をmap()メソッドを使って成型しているコンポーネントが<LinkList>です。
コンポーネント名は、いっこ上のindex.js内で「import LearnMoreLinks from './components/LearnMoreLinks';」としてLearnMoreLinksに変えています。
リンクを作るためのコンポーネントが<TouchableOpacity>ですね。


(12)<TouchableOpacity>・・・</TouchableOpacity>
入れ子にされた「ビュー」(テキストとか画像とか)を画面上でタッチしたときの動作を指定するコンポーネントのようです。
onPressイベントに専用の関数を割り当てれば、リンクを作る以外の動作もできそうです。
テンプレートAppの場合のように、URLをブラウズする場合、openURLInBrowser(リンク先URL)を使えばいいのですね。
openURLInBrowserは、「import openURLInBrowser from 'react-native/Libraries/Core/Devtools/openURLInBrowser';」でimportできるようです。



これで、一通りテンプレートAppの中身を読んでみたって感じです。
理解度は低いですが、納得いかないって部分とか、意味分かんね はちょっと減った。
ReactベースでJavaScript(JSX)を勉強したけど効果あったのかな?
・ReactDOM.renderは出てこないのね。
・React Nativeの場合、HTMLタグは出てこない?
・CSSファイルも出てこない?インラインで定義?
・コンポーネントの定義/書き方みたいなのは同じ?

まあこんな状態ですが、次は独自の処理・アプリを作って行きたいと思います。

たぶん、どこぞのサンプルをマネしまくることになるとは思いますが・・・
さるなんで。

では、この続きはまたいつか。
(m__)m




スポンサーサイト





コメントの投稿

非公開コメント

カレンダー
01 | 2024/02 | 03
- - - - 1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 - -
プロフィール

さるもすなる

Author:さるもすなる
さるです。別HPサイト「さるもすなる」から侵食してきました。 山菜/きのこ、それとタイトルにしたPPバンド籠のことをメインに徒然に・・・・暇を持て余したさるの手仕事:男手芸のブログってことで。

最新記事
最新コメント
月別アーカイブ
カテゴリ
天気予報

-天気予報コム- -FC2-
本家のHPのトップ
山菜や茸の話です
PPバンドの籠作品と作り方です
投稿をお待ちしております



PVアクセスランキング にほんブログ村 にほんブログ村 ハンドメイドブログへ



マニュアルのお申し込み



検索フォーム
リンク
RSSリンクの表示
ブロとも申請フォーム

この人とブロともになる

QRコード
QR