そーす

I'm a programmer in Fukuoka. Please contact me saubre.app[at]gmail.com or Twitter DM.

Github Pagesにブログを乗り換えます

GithubPages + NextjsのSPAです。

NextjsといってもGithubPagesではサーバーは建てれないのでStatic Export機能を使って作ってます。

ブログ記事はGithubのIssueを使ってます。

乗り換え理由は無料版だからかわからないですがはてなブログが重すぎるからです。

あとはてなブログほど高機能も求めてないし、自分で作るほうが自由度あるしいいかなーと思っていました。

あと最近スパムコメントが毎日来るようになって…

まぁPVとか大幅に減ると思いますし、SEOも弱いでしょうが軽いし自由なので目的は達成してます。

https://ryohlan.github.io/

UdemyでReactNativeの講座を公開しました

めっちゃ大変でした…

カリキュラム作ったり動画撮影したり編集したりするのめちゃくちゃ大変で、

あとウチが動画撮影する環境に全く適していなくて(子供がいたり、上空を飛行機が飛んだり、夜は貨物が走ったり)、だいたい深夜・早朝しか作業できなくて全然進みませんでした(笑)

最初は10分の動画取るのに何回も撮影して1時間位かかってたなー

とりあえず公開までは行けたので宣伝しておきます。

www.udemy.com

3月中までに使える無料クーポンを10名分作りましたので、もしよろしければ使っていただきたいと思います。

上記のリンクから登録していただくとクーポン適用になるかと思います。

とはいえ、結構前提知識必要な体で進めているのでわかりにくいかもしれません…

基本的には実際にReactNativeでアプリを作りながら作り方を学ぶという感じで作っているので、ES2016とかReactとかの細かい説明などしていないです。

カリキュラム作ってみて思ったのは割と自分の前提知識に頼って開発していたんだなぁと感じました。

そのあたりも全部やろうとしたら公開は来年になるのでは…と思ったのでReactNativeでアプリを作る所に焦点をあててカリキュラム組んだつもりです。

菩薩の気持ちでレビューとかいただけると喜びます。(豆腐メンタル

動画撮影した感想としては「Youtuberすげぇ」です。ヒカキンすげぇ…

福岡ゆるっとIT交流会 vol.3「モバイルアプリを作っている人の話を聞く会」

yurutto-it.connpass.com

「ReactNative枠よろしく!」

と言われたのででます。

珍しくアプリの話する会なので仲間を探してきます。

それに向けてFlutterもいじくり回してる途中。

「A Tour of the Dart Language」をやりました

www.dartlang.org

Flutterのβ版発表やDart2の発表で話題のDart

勉強したことがなかったのですが、公式のドキュメンが結構しっかりしており、その中の「A Tour of the Dart Language」という基礎を学ぶチュートリアルがあったのでやってみました。

www.dartlang.org

また、「DartPad」というオンラインでDartのコードが書けるサービスもあるのでチュートリアル見ながらDartPadで動かして確認という形で進めました。

ちなみにこの以下はDartの説明では無くただの感想です。

Dartのクラス定義なんかは

class MySample {
  String name;
  
  MySample(String name){
    this.name = name;
  }
}

void main() {
  MySample sample = new MySample('Ryohlan');
  print(sample.name);
}

このように書くことができます。

このコードはDartでもJavaでも動くコードですね。

ただ、Dartだと以下の方が推奨されています。

class MySample {
  String name;
  
  MySample(this.name);
}

この推奨される書き方はDartが公式で「Effective Dart」という形である程度のガイドラインを敷いています。これはチーム内での記述を揃えたりコードレビューするときなどに非常に有用です。

www.dartlang.org

さらに、ガイドラインに即したコードフォーマッターも用意してあります。

www.dartlang.org

このあたりがしっかりしていると決め事が少なくなるし「公式がとりあえず提供しているから」という文句である程度収まりがつきます。

構文はJavaに似ている所があり、Javaをやったことがあるプログラマならすんなりと書くことができそうな印象でした。

とはいえ、関数がファーストクラスオブジェクトであったり型推論があったりNull安全な機能があったりAsyncAwait、Generator…とだいぶ提供している機能が違います。

ただ言えるのはいわゆるモダンな機能を実装している言語である、ということでしょうか。

Dartを触ろうと思ったきっかけは、Flutterのβ版が出たこととDart2が出たからです。

Flutterは1年くらい前のα版のときから知ってはいたのですが、正直TypeScriptがGoogleの社内標準言語として発表されたり、

www.publickey1.jp

KotlinがAndroidの開発言語として発表されたりと

www.publickey1.jp

していたのであまり期待はしていませんでした。(ごめんなさい

そんな中Flutterのβ版とDart2の発表だったのでGoogleDart, Flutterに本気なのかなと思い直し、実際Dartを触ってみると個人的には非常に書きやすく読みやすそうだなと思いました(プロダクションで使ってみないとわかんないですが…)。

一応Dart自体はマルチプラットフォーム対応で「Dart for Web」や「Dart VM」などありますが、

まずはFlutterでアプリを作ってみてもう少しちゃんした手応えを感じたいと思います。

FukuokaJSにてReact Native ExpoについてLTしてきました

www.slideshare.net

FukuokaJSというイベントでLTしてきました

fukuokajs.connpass.com

やっぱ福岡だとReactもReactNativeも全然やってるひといなくて非常に疎外感がありますが、頑張っております。

ネタとしてはいくつか考えていたのですが、

そもそもReactの利用者が少ないっぽいのでNextJSとかReactとかReactNativeの話しても微妙っぽいと思って

「ネイティブ触らなくてもJSでネイティブアプリ作れるExpo」

みたいな雑なLTになりました。

今更Expoかよ、みたいな感じなんですがやっぱり知らない人とか結構いたようでLTしてよかったなーと思いました。

しっかし福岡Vue強いなーーーーーーー

オブジェクトの配列の重複削除

const merge = (newList, oldList, key) =>
  Object.values([...oldList, ...newList].reduce((a, b) => {
    a[b[key]] = b;
    return a;
  }, {}));

const l1 = [
{ id: '1', value: 'l1v1' },
{ id: '2', value: 'l1v2' },
{ id: '3', value: 'l1v3' },
];

const l2 = [
{ id: '2', value: 'l2v1' },
{ id: '4', value: 'l2v2' },
{ id: '5', value: 'l2v3' },
]

console.log(merge(l1, l2, 'id'));
0: {id: "1", value: "l1v1"}
1: {id: "2", value: "l1v2"}
2: {id: "3", value: "l1v3"}
3: {id: "4", value: "l2v2"}
4: {id: "5", value: "l2v3"}

重複があった場合は第一引数(new)の方を残す感じ。重複チェックしたいオブジェクトのキーをkeyに指定。

なんか他にいい方法ありますかね。

Proton-native

Proton Native - React Native for the desktop, cross compatible

https://proton-native.js.org/SVG/Artboard%201.svg

Reactを使ってデスクトップアプリが作れるライブラリが公開されていました。

なんでも

Create native desktop applications through a React syntax, on all platforms Same syntax as React Native

だそうです。

libuiというマルチプラットフォームGUIライブラリがあるのですがそれをnodeから使えるようにするlibui-nodeというライブラリがあって、Proton-nativeではProton-nativeのオーナーがlibui-nodeをフォークしているものを取り込んでいるようです。

このあたりはReact Nativeっぽさがありますね。

Quick Start

Proton Native - React Native for the desktop, cross compatible

してみました。

f:id:saburesan:20180216075211p:plain

これだと面白くないので、リポジトリに含まれてたDemo.jsの中身をコピってみます。

https://gyazo.com/d6ce18deadab61313bf91b809744a59e

色々試してみた

import React, { Component } from 'react';

import { render, Window, App, TextInput, Dialog, Box, Button, Checkbox, Picker, ProgressBar, Text } from 'proton-native';

class Example extends Component {
  state = {
    formText: '',
  }

  render() {
    return (
      <App>
        <Window title="Example" height={500} width={500}>
          <Box>
            <TextInput stretchy={false} onChanged={(formText) => this.setState({ formText })}/>
            <Text>{this.state.formText}</Text>
            <Button onClicked={() => Dialog('Error', {title: "Button Clicked"})}>Button</Button>
            <Box padded height={100} vertical={false}>
              <TextInput stretchy={false} onChanged={(text) => Dialog('Error', {title: text})}/>
              <Button onClicked={() => Dialog('Error', {title: "Button Clicked"})}>Button</Button>
            </Box>
            <Checkbox>This is a checkbox</Checkbox>
            <Picker>
              <Picker.Item>Option 1</Picker.Item>
              <Picker.Item>Option 2</Picker.Item>
              <Picker.Item>Option 3</Picker.Item>
            </Picker>
            <ProgressBar value={-1} />
          </Box>
        </Window>
      </App>
    );
  }
}

render(<Example />);

https://gyazo.com/3858156a592e22b9e5772c6e55c0a74e

まとめ

React/ReactNativeのようなstyleは今のところ変更できないようです。

今後に期待ですね。

広告を非表示にする

アウトプットして起きたこと

ブログやらLTやらで少しづつアウトプット出してて身に起きたことです。

名前を覚えられる

前にReact Nativeについての発表を何回かしたのですが、同僚がある勉強会(私は行ってないです)に行ったときに名刺交換で

「React Nativeの〇〇さんがいる会社ですね!」

って言われたそうで。嬉しい。

採用の応募がある

React, React Native, Kotlinなど流行りのものをやっていると「福岡 React Native」とかで引っかかるんですかね。

福岡で働きたいって人からちょいちょい採用の連絡が来ます。

外国人が多いですね。

弊社、インドネシア向けの事業しかやってないので今のところ基本的に外国人採用が多いです。

応募お待ちしております!

仕事の依頼がある

これも国内外関わらず来ます。

海外から仕事の依頼があったのはびっくりしましたね。

相手は日本語話せない感じですが、

「ブログとかGithub見たぜ〜、うちのチームに入らないか?」

ってくる感じ、これがインターネッツ!!

まとめ

アウトプットすると何故か海外とのつながりができる。

プログラミングってすごい。

TypeScriptでstyled-componentsに独自のPropsを渡したい

www.styled-components.com

最近はStyled-Component使ってます。

もともとstyleだけを分ける方法は使って無くて、

// Styleで分ける方法
const styles = {
  title: {
    fontSize: '2rem',
   color: '#333',
  },
};

export = ({ children }: Props) => (
  <main>
    <h1 style={styles.title}>{children}</h1>
  </main>
);
// コンポーネント毎に分ける方法
const Title = ({ text }: { text: string }) => (
  <h1 style={{ fontSize: '2rem', color: '#333'}}>
    {text}
  </h1>
);

export = ({ text }: Props) => (
  <main>
    <Title/>{text}</Title>
  </main>
);

こんな感じでコンポーネント毎に分ける方が好みでした。

コンポーネント名で判別できる方がわかりやすいですし、見た目もスッキリします。

しかしながらコンポーネントを分けていく上記の書き方だとコード数が増えるのが悩みでした。

styled-componentはそんな悩みを解決してくれたやつでした。

const Title = Styled.h1`
  font-size: 2rem;
  color: #333;
`;

export = ({ text }: Props) => (
  <main>
    <Title>{text}</Title>
  </main>
)

いい感じに私がやりたかったことを実現してくれています。

あとcss本来書き方(ハイフン使える)で記述できる点やhoverやメディアクエリも書くことができるのは大きいですね。

新たな悩み

styled-componentsにはstyleを定義しているテンプレートリテラルの中でPropsを受け取ることができます。

このお陰でPropsによってスタイルを変えることが容易になっています。

const Title = Styled.h1`
  font-size: 2rem;
  color: ${({ active }: any)=> active ? '#AAA' : '#333'};
`;

export = ({ text, active }: Props) => (
  <main>
    <Title active={active}>{text}</Title>
  </main>
)

しかし、TypeScritpだとTitleactiveが渡せません(エラーが出ます)。

理由はh1のPropsにactiveが定義されていないからです。

じゃあコンパイル通すにはどうするんだって話ですが、とりあえず

1.Propsで変化するStyleだけ別で書く

2.Object spreadで回避

3.コンポーネントを返す関数(前に私がやっていた方法)を定義する

かなーと思いました。

Propsで変化するStyleだけ別で書く

const Title = Styled.h1`
  font-size: 2rem;
`;

export = ({ text, active }: Props) => (
  <main>
    <Title style={{ color: ${active ? '#AAA' : '#333' }}}>{text}</Title>
  </main>
)

うーん、微妙。

そもそも1つのコンポーネントのスタイルを別々で定義するのはバグの温床っぽい感じがするので嫌ですね。

Object spreadで回避

const Title = Styled.h1`
  font-size: 2rem;
  color: ${({ active }: any)=> active ? '#AAA' : '#333'};
`;

export = ({ text, active }: Props) => (
  <main>
    <Title {...{active}}>{text}</Title>
  </main>
);

コンパイルは通りますが、TitleのPropsのタイプチェックはもちろん行われていません。

TypeScript使ってタイプチェック無視する書き方は出来る限り避けたいですね…

[追記] これコンパイル通りません。onClickなどの存在するPropsを追加するとコンパイルが通るようです。

コンポーネントを返す関数(前に私がやっていた方法)を定義する

const Title = ({ active, children }: { active: boolean, children: any }) => {
  const Cmp = Styled.h1`
    font-size: 2rem;
    color: ${({ active }: any)=> active ? '#AAA' : '#333'};
  `;
  return <Cmp>{children</Cmp>
}

export = ({ text, active }: Props) => (
  <main>
    <Title active={active}>{text}</Title>
  </main>
);

うーん、って感じです。

結論

悩んでます。

無印のクラックプレッツェルチョコレートが美味い

www.muji.net

これがマジで美味い。

美味すぎる。

今日大名店のやつ買い占めてきた。

2つ以上で10%OFFだったので。

1つ100円なんで買ってみてください。

Kotlinでa == 1 && a == 2 && a == 3

前回の記事はJavaScripta == 1 && a == 2 && a == 3が成り立つにはどうすれば良いか、という内容でしたが元記事のブコメ

プロパティある言語(C#, Swiftなど)ならトリッキーなことしなくても普通にできちゃう

とりあえずKotlinのDelegation。

一番楽ですぐ思いつく方法はコレじゃないでしょうか

import kotlin.reflect.KProperty

class Delegate {
    var count = 0

    operator fun getValue(thisRef: Any?, property: KProperty<*>): Int {
        count++
        return count
    }
}

fun main(args: Array<String>) {
    val a by Delegate()
    if ( a == 1 && a == 2 && a == 3) {
        println("true")
    }
}

JavaScriptの比較演算子の話

stackoverflow.com

これ、よく思いつくなーと感心しました。

普段等価演算==使うことないのですが、==の場合だと上記の回答のようなことができるようです。

valueOfでも大丈夫だって書いてあったのですが、toStringvalueOfどっちも定義されている場合、toStringが呼ばれることはありませんでした。

% node
> const a = { toString: () => console.log("toString"), valueOf: () => console.log("valueOf") };
undefined
> a
{ toString: [Function: toString], valueOf: [Function: valueOf] }
> a == 1
valueOf
false
> a == "1"
valueOf
false
> a === 1
false
> a === "1"
false
>

valueOfのリファレンスには

developer.mozilla.org

文字列型の文脈にあるオブジェクトは toString メソッドを通じて変換されますが、

とあるんですが、

> console.log(a + " string")
valueOf
undefined string
undefined

文字列の文脈って上記のようなやつは違うんですかね。

Next.jsに動的ルーティングを追加する「next-routes」

Nextjsにはデフォルトでルーティング機能があります。

[root_directory]/pages/ディレクトリ構成がそのままルーティングになります。

しかし、RESTfulなURIにする場合はサーバーの設定をカスタマイズして手動でしなければなりません。

そのような動的なルーティングを追加するためのモジュールがnext-routesです。

github.com

動的なルーティングを追加

たとえば、/users/show?id=ryohlan/users/ryohlanというルーティングを貼りたい場合は

# routes.js
const routes = module.exports = require('next-routes')()

routes
.add('/users/:id', '/users/show')

このように定義して、

# server.js
const next = require('next')
const routes = require('./routes')
const app = next({dev: process.env.NODE_ENV !== 'production'})
const handler = routes.getRequestHandler(app)

const {createServer} = require('http')
app.prepare().then(() => {
  createServer(handler).listen(3000)
})

という風にサーバーの設定を変更することで

/users/ryohlanへのアクセスを/users/show?id=ryohlanで受けることができます。

クリックで遷移の時

Nextjsではクリック遷移の時はNextimport Link from 'next/link'でLinkコンポーネントを使うのですが、

next-routesにはLinkコンポーネントもあるので代用することで動的なルーティングを使うことができる

# routes.js
const routes = module.exports = require('next-routes')()

routes
.add('users_show', '/users/:id', '/users/show') # 第1引き数が/で始まらない場合はルーティングのIDとして使うことができる

# pages/users/show.js
import {Link} from '../routes'

export default () => (
  <div>
    <Link route='users_show' params={{id: 'ryohlan'}}>
      <a>Hello world</a>
    </Link>
  </div>
)

react-native-firebaseのiOSのワークアラウンド

react-nativeでFirebaseを簡単に使えるようになるreact-native-firebaseというライブラリがあります。

rnfirebase.io

ですが、react-native v0.51.0ではiOSの設定がドキュメント通りでは動きません。

そのワークアラウンドについて書いておきます。

RNFirebaseをpodからLibrariesに直接インポートする

ドキュメント通りにreact-native linkをするとPodfile

   pod 'RNFirebase', :path => '../node_modules/react-native-firebase'

が追加されていると思いますが、これを消します。

次に、Finderを開いてnode_modules/react-native-firebase/ios/RNFirebase.xcodeprojXcodeLibrariesにドロップします。

f:id:saburesan:20171213005611p:plain 

f:id:saburesan:20171213005643p:plain

Linked Frameworks and LibrariesにlibRNFirebase.aを追加

f:id:saburesan:20171213010021p:plain

とりあえずこれで動きます。

FirebaseMessagingを追加する時

rnfirebase.io

FirebaseMessagingを追加するステップでAppDelegate.m#import "RNFirebaseMessaging.h"を追加する作業があるのですが、

このヘッダが見つからないのでビルドが通りません。

これはXcodeHeader Search Pathに以下のパスを追加する必要があります。

$(SRCROOT)/../node_modules/react-native-firebase/ios/RNFirebase/messaging

f:id:saburesan:20171213010542p:plain

これでFirebaseMessagingのビルドが通るはずです。