のらねこの気まま暮らし

技術系だけど、Qiita向きではないポエムとかを書くめったに更新されないヤツ

ReactNativeにNativeBaseを導入してUIを整える

概要

天気の情報を入れた、が! CloudsとかClearとか言われてもわけわからん! いつの天気!? みたいに思うのでとりあえずUIをそれっぽくしてみようと思った。

前回:

mizuki-r.hatenablog.com

情報設計

L2. いつ L1. 天候 L3. 気温, 湿度, 気圧 L4. 更新

対応フロー

  1. リファクタリング 1.1. 起動時に天気を取得する
  2. ワイヤーフレームの作成 2.1. ヘッダ 2.2. 天気アイコンの表示 2.3. 今日の天気レイアウト 2.4. 更新ボタンのレイアウト

実装調査

起動時初期化

ContainerでcomponentDidMount時にasyncAction発行すれば行けそう。

UI

NativeBase

他のMaterial系とかも探したけど、 ここ数ヶ月でメンテされてて、情報がありそうなフレームワークがぱっと見みつからなかった。

そういうの探すのにおすすめな記事とかあれば知りたい。 そういうの探すのにおすすめな記事とかあれば知りたい。(こういうのとか)

Comonents

まあこの辺使えばいけるんじゃないの?的なやつ。

実装

  • API通信が「取得」から「読み込み(自動)」「再読込(ユーザアクション)」に別れたことで、UseCase, Action, Reducerに変更が必要となった
    • めんどくさくてUseCaseだけ分けた
    • あとで違うインタラクションにしてくれって言われたときに困るかもしれない
      • ローディングの有無とか、表示の仕方とか
      • 困らないかもしれない
    • Viewから見て別れていれば一旦おk
      • いやこれ、絶対あとで「クソだろ」って思う
  • react-baseがコケた
    • Error: Unable to resolve module 'create-react-class'
  • NativeBaseでReactNativeのComponentを置き換え
  • NativeBaseでアイコン利用
    • type, name を指定するが、☓になる
    • 名前を変えても☓
    • react-native linkしてなかった
    • デフォルトはIonicons
  • ボタン+アイコンがいい感じの配置にならない
    • ドキュメントのコードとキャプチャが違う
    • サンプルを示してくれ!!!!

Error: Unable to resolve module create-react-class

Loading dependency graph, done.
error: bundling failed: Error: Unable to resolve module `create-react-class` from `/Users/mizuki/project/rnapp-weather/node_modules/native-base/dist/src/basic/Picker.android.js`: Module `create-react-class` does not exist in the Haste module map

インストールで解決。

$ npm install --save create-react-class

NativeBaseの利用

$ npm install --save native-base
$ react-native link

Android EmulatorのScreen shot

$ adb shell screencap -p /sdcard/screen.png
$ adb pull /sdcard/screen.png /tmp/screen.png
$ adb shell rm /sdcard/screen.png
$ open /tmp/screen.png

参考: MacでAndroid開発中に手軽にスクリーンショットを撮る

完成図

f:id:ry_mizuki:20180624224206p:plain

React Native に Reduxを加え、ロジックを実装する

概要

React Native入門シリーズその3。 Reduxを導入してAPI通信してViewに引き渡す。

前回: ReactNativeにTypeScriptを導入する - のらねこの気まま暮らし

APIについて

OpenWeather

アプリについて

今回試すことが主軸にあって、 「こういうView」っていう提案まで考えてない。よって実用的ではないものだが、アプリの構成について考える土台として雑に作る。

インタラクション

本来なら、今の天気を取得しつつ予報も出すべきだが前述の通り手抜きで対応する。

  1. ボタンを押したら、天気の読み込みが始まる。
  2. 天気の読み込みが完了したら、天気の情報を表示する。

View設計

  • 今の天気を取得するボタン
  • 天気の状態をそのまま表示

アーキテクチャ

アプリの構造を考えるぞい。

選定

  • Redux Way
  • Redux Way Arrange
  • Ducks

Redux Way系は役割でコードを分ける、Ducksは関心でコードを分ける。

個人的にクライアントの関心はViewの側面から見たActionとアプリ全体から見たStateに分けられると思っていて、そこを密結合することに懸念がある(実際、Vuexでも結構悩んだ)。

今回はReduxについて真剣に考えるより、React Nativeを知ることが目的なので複雑な悩みを抱えたくない。

しかし、Redux Wayは僕の感覚に則さない...

ということで感覚的にしっくり来るようにRedux WayをArrangeする。

Redux Way Arrange

View層

React Componentを配置する。 Container,Presentational,AppRootを管理する。

UseCase層

Viewから入力を受け取り、dispatchのタイミングを制御する。 いざ名乗ってみると違和感しかない。 Containerと対応する。

Action層

ActionCreator。

UserCaseで構築したデータをActionにパッキングする。 ここはもっと隠蔽できると嬉しい。

究極、s2sとか使って自動生成したい。

Store層

Redux Storeの初期化と、Reducerの定義を担う。 Reducer基本的にStoreからしか参照されないしっていうかStoreの一部だよね、の気持ち。

ReducerはViewではなく、アプリ内のドメインと対応する。 Stateはアプリにおける情報のドメイン

Service層

名前に悩んだけどまあとりあえず。

外部APIとの通信、アプリへの最適化を担う。 だいたい外部APIを使う場合(それが自前で用意したAPIだとしても)要求以上の実装がされがちなので、そういう本質的ではないが必要なことをまとめておく場所。

基本的にUseCaseからしか呼ばれない。

実装フロー

事前想定:

  1. 天気取得ボタンの作成
  2. 天気取得のUseCaseの作成
  3. Reducerの雛形
  4. OpenWeather API取得の実装
  5. UserCase内でAPI呼び出し
  6. weather用のReducerを定義
  7. ViewにReducerから取得したデータを表示

実際:

  1. React + Reduxの雛形作成
  2. ボタンの作成
  3. 天気取得のUseCaseの作成
  4. Actionの作成
  5. Reducerの作成
  6. 型の定義(Action, State, Props, etc)
  7. Weather用のReducerを定義
  8. ここでContantsが必要だと判断
  9. OpenWeather API取得の実装
  10. weatherのReducerに実データとローディングフラグを実装
  11. Viewに読み込み時の処理と天気表示を実装

つまったところ

  • connectの実装と型定義
  • Object.assignの引数の順番間違えた
  • OpenWeather APIの仕様調査と型定義

モジュールの変化

core

  • react-redux
  • redux
  • @types/react-redux
  • @types/redux

service

  • axios
  • qs
  • @types/qs

所感

TypeScriptの警告つぶしが結構面倒だった。 Reducer定義しないといけないことを知った。 OpenWeatherAPIの仕様以外と知らなくて手間取った。 土台ができちゃえばあとは継ぎ足しで行けるかなって思った。 あれ、ReactNativeってなんだっけ?

github.com

ReactNativeにTypeScriptを導入する

概要

前回の続きです。 できたてホヤホヤのプロジェクトにTypeScriptを導入する。

環境

  • react v16.3.1
  • react-native v0.55.2
  • react-native-cli v2.0.1

依存モジュールのインストール

$ npm install -D \
  typescript \
  node-libs-react-native \
  react-native-typescript-transformer \
  @types/react \
  @types/react-native \
  @types/jest
$ npm audit fix 

tsconfigの設定

{
  "compilerOptions": {
    "target": "ES2017",
    "module": "ES2015",
    "jsx": "react-native",
    "rootDir": "./src",
    "strict": true,
    "skipLibCheck": true,
    "noImplicitAny": true,
    "noImplicitThis": true,
    "alwaysStrict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "moduleResolution": "node",
    "baseUrl": "./",
    "esModuleInterop": true,
  },
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "node_modules"
  ]
}

CLIにTransformをフックする

const extraNodeModules = require('node-libs-react-native')

module.exports = {
  extraNodeModules,
  getTransformModulePath() {
    return require.resolve('react-native-typescript-transformer');
  },
  getSourceExts() {
    return ['ts', 'tsx'];
  }
}

App.jsを書き換え

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

export default class App extends Component {
  render() {
    return (
      <View style={styles.container}>
        <Text>Open up App.js to start working on your app!</Text>
        <Text>Changes you make will automatically reload.</Text>
        <Text>Shake your phone to open the developer menu.</Text>
      </View>
    );
  }
}

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

実行

$ npm run start
$ npm run android

初心者がReactNativeを使ってAndroidで起動できるようにするまでの記録

概要

諸事情でReactNative触る機会があるんだけど、 Nativeは経験が薄く、Reactもそんなにガッツリ触ってないのでこれを期に勉強しようと思ったのでまとめ。

実行環境

悲しいかな、High Sierraにできなかったんだこの端末...

入門準備

めんどくさいので今回はAndroidのみ。

Android

SDKMan

JDKや管理用にSDKMANを入れる。

Home - SDKMAN! the Software Development Kit Manager

$ curl -s "https://get.sdkman.io" | bash
$ source "$HOME/.sdkman/bin/sdkman-init.sh"

※このとき、tr, ttにshellでalias貼ってるとエラーになるので注意。

~/.bashrcを開くとSDKMANの初期化コードが含まれている。(えーーーー) zsh使いなのでzprofileに移す...

$ echo '
#THIS MUST BE AT THE END OF THE FILE FOR SDKMAN TO WORK!!!
export SDKMAN_DIR="/Users/mizuki/.sdkman"
[[ -s "/Users/mizuki/.sdkman/bin/sdkman-init.sh" ]] && source "/Users/mizuki/.sdkman/bin/sdkman-init.sh"
' >> ~/.zprofile

いや、よしんばbashはいいとしても、rcに書き込まないでくださいよ、こちとらgitで管理してんやぞ? profileあるやろ。なんで?

.zprofileはお使いのshellに置き換えてご利用ください。

$ sdk version

SDKMAN 5.5.13+272

JDKのインストール

$ sdk list java

一覧が出てくる。 今回は諸事情によって1.8が使いたい。

$ sdk install java 8.0.171-oracle
$ java -version
java version "1.8.0_171"
Java(TM) SE Runtime Environment (build 1.8.0_171-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.171-b11, mixed mode)

ok

Android Studio

Download Android Studio and SDK tools  |  Android DevelopersからAndroidStudioをダウンロードしてくる。 (この時点での最新は3.1.3 for Mac

インストール類は時間かかるから先にやるのがおすすめ

ReactNativeのガイダンスに従ってインストールを進める。

  1. ウィザードが起動するので、Choose the type of setup you want for Andriod Studio のメッセージが出てきたらCustomを選択。
  2. Select UI Theme は好きなやつ
  3. SDK Components Setupは以下のものを選ぶ 3.1. Android SDK (チェック済み) 3.2. Android SDK Platform (チェック済み) 3.3. Performance (Intel ® HAXM) (チェック済み) 3.4. Android Virtual Device (チェックする)
  4. このさきは任意で

Android Virtual Deviceエミュレーターのやつ。

ウィザードが完了したら Welcom to Android Studio 画面に来るので、Configure から SDK Manager を起動。

なんかいい感じに選んでいれてく。

最後にANDROID_HOMEにパスを通す。

$ echo '
export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH=$PATH:$ANDROID_HOME/tools
export PATH=$PATH:$ANDROID_HOME/tools/bin
export PATH=$PATH:$ANDROID_HOME/platform-tools
' >> ~/.zprofile

あとでadbとか使うからね。

ReactNative Projectのセットアップ

$ npm install -g create-react-native-app
$ create-react-native-app rnapp-weather

Node実行環境

$ ndenv install v10.5.0
$ ndnev local
$ ndenv rehash

# create-react-native-appで入ったやつを消
$ rm -rf node_modulesす
$ rm yarn.lock

# re:install
$ npm install
added 1302 packages from 787 contributors and audited 35887 packages in 55.633s
found 5 vulnerabilities (2 low, 2 moderate, 1 high)
  run `npm audit fix` to fix them, or `npm audit` for details

npm 6で追加されたauditのレポート。 npm audit fixを使うと、解決策が提示されている場合は解決してくれる。

+ react-native-scripts@1.14.1
added 6 packages from 17 contributors, removed 82 packages and updated 4 packages in 12.801s
fixed 2 of 5 vulnerabilities in 35887 scanned packages
  2 vulnerabilities required manual review and could not be updated
  1 package update for 1 vuln involved breaking changes
  (use `npm audit fix --force` to install breaking changes; or do it by hand)

一旦これでよしとしよう。

実行

$ npm start
10:20:11: Unable to start server
See https://git.io/v5vcn for more information, either install watchman or run the following snippet:
  sudo sysctl -w kern.maxfiles=5242880
  sudo sysctl -w kern.maxfilesperproc=524288

Start script hangs without error when there are no available inotify watches · Issue #234 · react-community/create-react-native-app · GitHub

なるほど

$ sudo sysctl -w kern.maxfiles=5242880
$ sudo sysctl -w kern.maxfilesperproc=524288

リトライ

$ npm start
10:22:03: Starting packager...

okそう。

ejectの実行

このままだとReactNativeしかないのでNative使えるようにする

$ npm run eject

> rnapp-weather@0.1.0 eject /Users/mizuki/project/rnapp-weather
> react-native-scripts eject


We didn't find any uses of the Expo SDK in your project, so you should be fine to eject to
"Plain" React Native. (This check isn't very sophisticated, though.)

We strongly recommend that you read this document before you proceed:
  https://github.com/react-community/create-react-native-app/blob/master/EJECTING.md

Ejecting is permanent! Please be careful with your selection.

? How would you like to eject from create-react-native-app? React Native: I'd li
ke a regular React Native project.
We have a couple of questions to ask you about how you'd like to name your app:
? What should your app appear as on a user's home screen? Weather
? What should your Android Studio and Xcode projects be called? Weather

How would you like to eject from create-react-native-app?

そのままEnter

What should your app appear as on a user’s home screen?

Weather

What should your Android Studio and Xcode projects be called?

Weather

Android端末の接続

手元にないのでエミュレーターで。 ーーって思ったけどどこからDevice Manager起動するのかわからねえ...

仕方ないので新しくProject立ち上げる。 CLIとかどっからDevice Manager起動できひんの?

Virtual Devices起動できた、が、アイコン小さすぎてわからない。これは... 初心者辛くない...?

$ adb devices
List of devices attached
emulator-5554   device

接続を確認。

AndroidでReactNativeを実行

$ npm start

こっちでビルドして配信する。

別ターミナルを開いて、ビルドを実行。

$ npm run android

めったビルド走る。

わぁい赤ぁい

error: bundling failed: Error: Couldn't find preset "babel-preset-react-native-stage-0/decorator-support" relative to directory "/Users/mizuki/project/rnapp-weather"
diff --git a/.babelrc b/.babelrc
index 0f0c07d..57415c7 100644
--- a/.babelrc
+++ b/.babelrc
@@ -1,6 +1,6 @@
 {
   "presets": [
-    "babel-preset-react-native-stage-0/decorator-support"
+    "babel-preset-react-native"
   ],
   "env": {
     "development": {

うごいた

Hello World

しようとおもったけど疲れたので次にする。 hotreloadうごかん。

まとめ

導入で力尽きた

  • create-react-native-appしたらejectする
  • モジュール間のバージョン際なんてよくあること
  • emulatorはなにが起きてもおかしくないので強く心を保つ
  • hotreloadをする

3hくらいかかった。つかれた

github.com

React+Redux覚書

概要

React+Reduxを使ってアプリを書く機会があったが、 どちらもちゃんと触ったのは年単位昔なので思い出すために軽くコードを書いてみた。

ーーやつの備忘録。

こういうことを思ってこうしたいなって気持ちになったという記録。

基本構成

environment

  • Docker node:10.4.0-alpine

dependencies

  • react 16.4.1
  • react-redux 5.0.7
  • redux 4.0.0

devDependencies

  • babel-loader 7.1.4
  • babel-preset-react 6.24.1
  • webpack 4.12.9

基礎知識

  • React
  • Redux
    • connect
    • state
    • reducer
  • Component
    • Provider
    • Container
    • Presentational

所感

もともとSyntagme作るときに、Reduxのコードは読んでいたので一度読み直せば「あーはいはい」って感じだった。

ただ、当時思ったActionCreatorの扱いでやっぱり戸惑う。

ActionCreatorは、 * dispatchするオブジェクトを作る * 複雑なdispatchを隠蔽する

の役割があると感じていて、 その2つを共存させることに抵抗がある。

できれば役割わけたいなぁと。

もしかしたらMiddlewareがいい感じに隠蔽してくれるのかも知れないが、 初心者にはその歴史的経緯をさっくり理解するにはReduxの世界は広すぎる。

再設計

というわけで腹落ちする程度まで掘り下げた。

ディレクトリ構成

- src
  +- index.js
  +- views/
  | +- components/
  | +- containers/
  | | +- Home.jsx
  | +- App.jsx 
  +- usecase
  | +- home.js
  +- actions/
  | +- index.js
  +- store/
    +- index.js
    +- reducers/

index.js

  • App.jsxのマウント
  • アプリケーション全体の初期化処理

Views

React Componentを押し込める場所。 汎用的なものだけではなく、画面構成全部を含むので、Viewって名前空間にした。

App.jsx

  • Providerの構築
  • Redux Storeとの接続

Containers

  • Container Componentの置き場
  • Presentationalを一つ以上組み合わせる
  • ViewとUseCase, Stateを接続する

Components

  • Presentational Component
  • コンテキスト持っちゃ駄目よ
  • 小規模ならこれでいいけど、Componentの数が増えてきたらAtomic-Designとかをベースに分割したほうがいいかもしれない
    • が、必要ないならしないほうが無難

UseCase

  • 独自定義
  • 着想はAlminから
  • view ← 何らかのイベント → action の中間処理を担う
    • fluxで言うところのActionCreator
    • view側からの入力のハンドル
    • アプリの外側とのコミュニケーション
    • dispatchのタイミングのハンドル
  • 基本的にはContainerと対応する

Actions

  • Actionオブジェクトの作成
  • 程よい切り方がわからないけど機能単位で切るのがいいのかなぁ

Store

Redux Storeの定義。

index

  • createStoreの実行
    • reducer, initialState, middlewareの構築

initial-state

  • 初期Stateの定義

reducers

  • reducerの定義
  • 基本的にはアプリケーションにおける情報設計単位でファイルを切る
    • 必ずしも画面と対にはならない
    • 複数の画面で同じデータを使い回すことがある
    • 領域をビジネスロジックに基づいて区切るという意味で、ドメイン設計に近い

まとめ

  • React+Reduxで最低限腹落ちする構成を考えた

Macを外部ディスプレイにつなげた時のWindow配置を記憶したい!

背景

最近の僕は、GoogleChromeのタブを38個とか開いているようです。

Tabs OutlinerSpaces という拡張機能を併用して、 たっくさんあるタブを用途やカテゴリ毎にwindowに分割しているんです。

まあ、ぞれでもWindowは5,6個できるんですけど。

Tabs OutlinerとSpacesのおかげで管理は大分楽になったんですが、困ったことが一つありまして。

問題

普段はMac Bookを外部ディスプレイにつなげて普段作業しているんですよね。Mac Bookのディスプレイと外部ディスプレイ二枚。

会議や相談なんかあれば、外部ディスプレイの接続切ってMac Bookを持っていくわけです。 そして話し終えたら席に戻ってきて外部ディスプレイに接続する。

画面にでてくるのは、SlackやiTerm、そして5,6個重なったGoogle Chrome

微妙に位置を調整して、ワンクリックで目的のWindowを開けるようにしていたGoogle Chromeの位置を戻すのがもう、面倒でしかたないったらありゃしない。

さすがに、疲れました。

調査

そんなわけで、頼れるGoogle先生に聞いてみたんです。できないかって。

参考になったのは、以下の記事でした。

forget-me-not は残念ながらアクセス出来ませんでした。まあ2012年の記事だし。 代わりにStay の方を見てみました。

AppStoreで\1,800だったので、即買。

検証

先ほどの StayさえあればもうMBAをサブディスプレイに繋げるのは怖くない を見ながら設定してみました。

2,3回試しました。繋いで、はずして。

Google ChromeのWindow7枚とiTermとSlackだけ個別にstoreしてみました。 Mac Bookを開いたままコネクタを外すと、まあ位置画面に収まります。 そのまま繋げ直してみると、「Restoring windows」と表示されてガチャガチャwindowのサイズや配置が変わっていきます。

結論

なにこれ便利...!

お試しあれ

参考

2015年の振り返り

新年早々いろいろあって振り返ってる余裕が無かったので、それっぽいのをハリボテで。

2015年に書いた記事

当ブログ

mizuki-r.hatenablog.com

8記事!少ない!!

Qiita

qiita.com

qiita.com

2記事!少ない!!

2015年に発表したトーク(public)

www.slideshare.net

www.slideshare.net

www.slideshare.net

www.slideshare.net

4回!ま、まあ...

振り返り

JavaScript一色だなぁ...

ブラウザサイドからNodeJSまで。 ただ、使っているツールや関心の範囲はこの一年でだいぶかわってきたのかなと思う。

フロントエンドツールの開拓、WAFのアーキテクチャ設計、それに関連する各種ライブラリの選定等など、外部モジュールを触るのが多い一年だった。 MVCよくわからんっていう時期から、FluxやReduxを通じてアプリのアーキテクチャを考えていく中で、 単一のライブラリに頼るのも、複数を組み合わせるのもそれなりに模索が必要だと感じているのが年末だった。

2016年の抱負

ツールは揃ってきているけど、いま欲しいものが現状ない。 そういう「何がほしいのか」という部分を自分が適切に理解し、それに即したライブラリを模索・制作していきたいなとは思っている。

年が明けてから、FluxやReduxによって手放そうとしたMVC,DDDを取り戻す方向性を考えている。 技術的にModelとはどういうものか、というより、Model的な考え方をFlux上に載せつつ、効率的に開発できないかと考えている最近。

僕はもともとMVCについての理解が浅かったので、改めて勉強しようかなと思う。

余談

新年早々部屋が半分水浸しになって大変大変つらかったけど、この先は楽しい一年にしていこうとおもったのでした