私用環境を整理する・昨日はデザインパターン読書会だった

私用環境を整理する

先日この↑本を読んでいて、そうだなーと共感したのが 仕事のPCを私用のPCを分ける という話。

そもそも会社に行って仕事をする、ということは場所を切り替えることで意識を切り替えていたわけだけど、 場所が切り替わらなくなった場合、マシンを切り替えるといい、ということ。

本当にこれはそうでそのように実践しているわけですが、

つまりセットアップもそれぞれでしています。

そうすると仕事環境と私用環境に差が出てきてしまうので、ときどきお手入れが必要になります。

私用環境は、そんなじ長い時間使わなかったりするので、ついついお手入れをさぼりがち。。 というわけで今久しぶりに私用環境のお手入れをしています。

みなさんこういうときどうしているのかなぁ。

お手入れは、おもに作業中の困ったに対して都度都度丁寧にやっていくこととした。 つまり、仕事環境と一気にあわせるぞ!というのではなく、朝活中などに出くわした環境差異に、その時やっていることの手をいったん止めて、その都度ちゃんと向き合うこと。

今日のお手入れ

  • Mac OS を Catalina にアップグレード(仕事環境はまだ High Sierra だけど)
  • peco が入っていなかった!ひどい

昨日はデザインパターン読書会だった

増補改訂版Java言語で学ぶデザインパターン入門

増補改訂版Java言語で学ぶデザインパターン入門

  • 作者:結城 浩
  • 発売日: 2004/06/19
  • メディア: 大型本

  • Java である
  • 今どき Iterator とか実装しないでしょう

という点などがあり、Rubyist にはあまり読まれない本なのかしら…と思いつつ、やっぱり「デザインパターン」を学ぶには相変わらず最有力候補っぽい?

しかし素養のない私には、読んでいて新しい発見もいろいろある。

こちらをながめつつ、「Ruby 力をあげていきたい」という気持ちは復刊されたこちらのほうがいいのだろうな!

コンポーネントのライフサイクル

コンポーネントのライフサイクル

初期化され、マウントされ、レンダリングされ、再レンダリングされ、アンマウントされ…というサイクルのなかで、

それぞれのフェーズに介入して処理を差し込むメソッドが用意されている。

Mounting フェーズ

  • constructor [void]
  • static getDerivedStateFromProps(props, state) [State | null]
  • render() [React.ReactNode]
  • componentDidMount() [void]

Updating フェーズ

  • static getDerivedStateFromProps(props, state) [State | null]
  • shouldComponentUpdate(nextProps, nextState) [boolean]
  • render() [React.ReactNode]
  • getSnapshotBeforeUpdate(prevProps, prevState) [Snapshot | null]
  • componentDidUpdate(provProps, prevState, snapshot?) [void]

Upmounting フェーズ

  • componentWillUnmount() [void]

Error Handling フェーズ

  • componentDidCatch(error, info) [void]
  • static getDerivedStateFromError(error) [State]

こうして見てみるとだいたい「メソッド名で何ができそうか」見当がつきますねぇ。 こういうのがあるよ、というのはまず覚えておく。

本文中に、ライフサイクルのなかで各フェーズとそれぞれのメソッドがどういう順番に呼ばれるかが表現された図があって、わかりやすかったです。

React コンポーネントのライフサイク ルって、バージョン 16.3 から 17 にかけて大きな変更が予定されててね

おっと。インターネットの便利情報では16系のメソッドが使われている可能性があるので、注意しましょう。

開発するときに心がけたいこと(のひとつ)

技術書典8が新型コロナウイルス感染症の影響により中止となったため、 オンラインで応援祭が開催されています。(2020年4月5日まで)

それで昨日こちらを購入しました。

techbookfest.org

テストコミュニティには以前何度か参加したことがあり、ふだん自分がいるRuby界隈の方々から聞くのとまた別方向からの「開発」の話を聞くのがとても新鮮でした。

その頃から「開発」に関わる人たちがどんな気持ちでお仕事しているのかを知ることは、自分が開発をしていくなかでとても大切なことであると思うようになりました。

たとえばデザインを担当する方、PdM的な役割を担当する方、CSなどサービスを利用するお客様と直接接する方、など…

そのひとつとして、QAの方の気持ちを知りたくて、↑を読みました。

QAの方々が「テストするときに心がけていること」って、開発するときに心がけるといいことにつながるのでは、と思います。

コンポーネントと props

コンポーネントと props

コード写したり本文読んでいたんですが、やっぱりちょっと「コンポーネント」という考え方が身についていない。

ja.reactjs.org

概念的には、コンポーネントJavaScript の関数と似ています。(“props” と呼ばれる)任意の入力を受け取り、画面上に表示すべきものを記述する React 要素を返します。

なるほど、「何はなくともコンポーネント」。 ボタンもひとつのコンポーネントなんですね。

今回のサンプルコードの場合だと、 App という親コンポーネントのなかで、Card という子コンポーネントが作られている。 さらにそのなかで…という感じなのですね。

とするとデータの流れが単一方向というのはこういう感じなのかな。

f:id:katoriexxxkatorie:20200312062853p:plain

で、親コンポーネントが自身の値を書き換えたいときは

親コンポーネントが自身の状態を変更する関数を子コンポーネントに渡して、 フォーム入力時に発火されるイベントにその関数を仕込んでおく

今回の場合だと、親 App コンポーネントにおいて定義した increment()decrement() を、子 Button に Props として渡して、コンポーネント内でクリックイベントに仕込んでおくことで、親 App の props が書き換わるようになっている。

新しいReactアプリ(TypeScript)の構築手順おさらい・Local State

最近運動不足が気になっているので、バランスボールに座りながら仕事できないかな?と考えています。 バランスボールは場所をとりそうなので、こちらを購入検討中。。

新しいReactアプリ(TypeScript)の構築手順おさらい

テスト用にちょろっとつくりたい時のために手順をおさらい。 semantic-ui もいれます。

$ npx create-react-app APP_NAME --template typescript
$ cd APP_NAME
$ yarn start    // 起動できるか確認
$ yarn add semantic-ui-react semantic-ui-css

index.tsx に import文を追加します。

import 'semantic-ui-css/semantic.min.css';

これでだいたいサンプルコードと同じようなアプリがつくれます。 package.json は省略。。

Local State

こちらにサンプルコードをプッシュしました。

github.com

型引数がふたつセットされていますが、ひとつめは Props の型引数で、今回は必要ないので空オブジェクトになっていて、 ふたつめが Local Sate の型引数で、AppState というすぐ上で定義したもの。

this.state に値は直接代入できないので、setState() メソッドを使用する。

setState() の引数に設定できるもの

  1. 設定したい値の State オブジェクト(State に固定値を設定するとき)
  2. (prevState, props) => newState の形式の、State と Props を引数として受け取り新しい State を返す関数(動的に変更したいとき)

Props

やっと「りあクト!」本文に戻ってきました。。

Props

サンプルコード(CharacterList.tsx

interface CharacterListProps {
  school: string;
  characters: Character[];
}

class CharacterList extends Component<CharacterListProps> {
  render(){
    const { school, characters } = this.props;

    return (
// 省略

CharacterListProps という型インターフェースを定義して、 CharacterList というコンポーネントを定義するクラス宣言のところで、型変数として呼び出している。 こうすることで、コンポーネントの Props の型を指定できる。 Component クラスの型引数にはデフォルトで空オブジェクト {} が設定されているので、Props が必要ないときは省略できる。

コンポーネントでは、タグ属性として渡された Props の値を、クラスのメンバー変数 props として扱うことができる。

インターフェースを定義するときに、要素名に ? をつけておくと、オプショナル定義となるので マウントするときに属性値を書いても書かなくてもどっちでもよくなる。

interface CharacterListProps {
  school?: string;
  characters: Character[];
}

省略された場合の処理を考えておく必要はある。

ジェネリクス

TypeScriptでジェネリクス(Generics)を理解するための簡単なチュートリアル | I am mitsuruog

こちらを参考にジェネリクスを使ったコードを書いてみました。

User クラスと Company クラスを定義して、それらの配列にオブジェクトを追加できるmerge関数を定義します。

class User {
  id!: number;
  firstName!: string;
}

class Company {
  id!: number;
  name!: string;
}

function merge<T extends { id: number }>(array: T[], newValue: T): T[] {
  const index = array.findIndex(item => item.id === newValue.id);
  if (index === -1) {
    return [
      ...array,
      newValue,
    ];
  } else {
    return [
      ...array.slice(0,index),
      newValue,
      ...array.slice(index + 1),
    ];
  }
}

const userArray = [
  { id: 1, firstName: 'Taro' },
  { id: 2, firstName: 'Hanako' },
];

console.log(merge(userArray, { id: 3, firstName: 'Tom' }));
console.log(merge(userArray, { id: 4, firstName: 'Mary' }));

const companyArray = [
  { id: 1, name: 'AAA' },
  { id: 2, name: 'BBB' },
]

console.log(merge(companyArray, { id: 3, name: 'CCC' }));

{ id: number } という制約のある T という型を定義して、merge関数の型定義に使用しました。