開発するときに心がけたいこと(のひとつ)
技術書典8が新型コロナウイルス感染症の影響により中止となったため、 オンラインで応援祭が開催されています。(2020年4月5日まで)
それで昨日こちらを購入しました。
テストコミュニティには以前何度か参加したことがあり、ふだん自分がいるRuby界隈の方々から聞くのとまた別方向からの「開発」の話を聞くのがとても新鮮でした。
その頃から「開発」に関わる人たちがどんな気持ちでお仕事しているのかを知ることは、自分が開発をしていくなかでとても大切なことであると思うようになりました。
たとえばデザインを担当する方、PdM的な役割を担当する方、CSなどサービスを利用するお客様と直接接する方、など…
そのひとつとして、QAの方の気持ちを知りたくて、↑を読みました。
QAの方々が「テストするときに心がけていること」って、開発するときに心がけるといいことにつながるのでは、と思います。
コンポーネントと props
コンポーネントと props
コード写したり本文読んでいたんですが、やっぱりちょっと「コンポーネント」という考え方が身についていない。
概念的には、コンポーネントは JavaScript の関数と似ています。(“props” と呼ばれる)任意の入力を受け取り、画面上に表示すべきものを記述する React 要素を返します。
なるほど、「何はなくともコンポーネント」。 ボタンもひとつのコンポーネントなんですね。
今回のサンプルコードの場合だと、 App という親コンポーネントのなかで、Card という子コンポーネントが作られている。 さらにそのなかで…という感じなのですね。
とするとデータの流れが単一方向というのはこういう感じなのかな。
で、親コンポーネントが自身の値を書き換えたいときは
親コンポーネントが自身の状態を変更する関数を子コンポーネントに渡して、 フォーム入力時に発火されるイベントにその関数を仕込んでおく
今回の場合だと、親 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
こちらにサンプルコードをプッシュしました。
型引数がふたつセットされていますが、ひとつめは Props の型引数で、今回は必要ないので空オブジェクトになっていて、
ふたつめが Local Sate の型引数で、AppState
というすぐ上で定義したもの。
this.state に値は直接代入できないので、setState() メソッドを使用する。
setState() の引数に設定できるもの
- 設定したい値の State オブジェクト(State に固定値を設定するとき)
(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関数の型定義に使用しました。
朝活で読書会をはじめました
いつもの朝会(1時間)で、毎週金曜日は結城浩さんの「デザインパターン入門」を読むことにしました。
- 作者:結城 浩
- 発売日: 2004/06/19
- メディア: 大型本
Javaは書いたことがないのですが、デザインパターンの本としては名著中の名著とうかがっているので、 Javaの環境を整えつつ読んでみます。 Rubyだったらどう書く?もできるとよさそう。
読書会は輪読スタイルです。(Ikejiri.rbのスタイルを踏襲) 今日は初回なので「はじめに」から読んでみました。
UMLやシーケンス図の丁寧な説明があったので、このあと本文で出てきても大丈夫そう。
Javaの言語仕様などはわからないことがあったときどこを見るのがよさそうなんだろう。。
JSX内でのコメント・ジェネリクス
JSX内でのコメント
JSX内はあくまでJavaScriptなので、JavaScriptのコメント記述方法を使用します。
ジェネリクス
「クラス宣言のとこ、Component
と今までComponentクラスを継承するときにな かったジェネリクスみたいなのがあります。これは何ですか?」
ジェネリクス? そういえば配列のところでも出てきていましたが、スルーしてしまっていました。
> const arr1: number[] = [1, 2, 3]; [1,2,3] > const arr2: Array<number> = [1, 2, 3]; [1,2,3]
<number>
と表現することで型変数を追加している。
CやC#を書く人にとっては「あぁジェネリクスね」ということらしいのだけれど、
Rubyからきた私には「???」なので、以下のドキュメントを読みました。
まだちょっと「???🤔」なので、以下のチュートリアルをやってみます。