Panda Noir

JavaScript の限界を究めるブログでした。最近はいろんな分野を幅広めに書いてます。

僕がテキストベースでコミュニケーションしたい理由

テレワークが始まり、コミュニケーションの主流は対面でのMTGではなくslackへと移行しつつあります。そこで感じたテキストベースコミュニケーションの良さと課題感を書きます。

テキストベースの良さ

まず、テキストとして残る。これが大きいです。コミュニケーションの証拠がしっかりと残るため、あとから見返したり検索したりできます。

例えば「あれ、〇〇さんに〇〇の件って伝えたっけ?」となったら検索すれば確認できるので楽です。

次に、非同期という点です。「とりあえずslackで投げたから返信待つ間に別のことやろう」というふうに、コミュニケーション以外の仕事と並行してできます。もちろんすぐに返信が欲しい場合はマズイですが、実際には緊急のタスクは少ないので問題になりづらいです。

最後に、テキストに起こすことでより相手に伝えやすくなります。自分の考えの整理にも繋がりますし、口頭でコミュニケーションを取るより、整理した上でわかりやすく説明できるはずです。

テキストベースの課題

もちろん課題もいくつかあります。

まず、各々のタイピング速度に依存してしまうこと。タイピング速度が遅いとそれだけ返信に時間がかかりますし、文章の推敲をするような余裕が生まれづらいです。しかし、全員のタイピング速度を上げるよう強要するなんてできません。口頭と比べてレスポンスの速さが各人に依存してしまうのは課題です。

また、非同期であるという点は課題でもあります。特に緊急の時やステークホルダーが多い時はMTGを開いたほうが早い場合が多いです。

これはやや違うのですが、テキストベースの利点の一つとしてパブリックな場で発信できるというものもあります。これにより、会話に参加してない人もログを追ったりできます。しかし、クローズドな場所で連絡してるとこの利点を享受できません。僕は発言の99%をパブリックな場で行って極力DMを使ってないのでよいですが、他の人もそうとは限りません。

結論

僕はテキストベースの方がトータル早くてエビデンスも残せるので、口頭より如実に優れていると思っています

プログラミング題材集

  • みんな知ってる
  • そこそこ実装のやりがいがある
  • 仕様の把握がいらない(既に知ってる)

「あの言語を学びたいけど題材がない!」って時に活用ください。

アプリ編

  • TODO リスト
  • Twitter
  • カレンダー、予定表
  • Pixiv(画像ギャラリー)
  • ブログ(CMS)

ゲーム編

TUIでできるゲームばかりなので、どの言語でも実装できます。対戦用AIを考えるのも楽しいです。

  • テトリス
  • 2048
  • リバーシ
  • トランプゲーム

CLIツール編

有名なコマンドで、ちょっと面白いのを選んでみました。

  • ls
  • git
  • less
  • cal
  • jq
  • エディタ(nano や vim、Emacsなど)

シェルの実装をするのも面白いでしょう。

言語編

仕様が比較的カンタンな言語を選定しました。

  • Lisp
  • brainf**k
  • Lua

パズル系

パズルソルバーは競プロ的な要素もあります。解けると楽しいパズルを選んでみました(難易度が高いものもあります)

  • 数独ソルバー
  • チョコレートパズル(ペントミノ)ソルバー
  • ルービックキューブ
  • 15パズル

React の key をちゃんと使えないと起こる問題

「React の key に配列の添え字を使ってはいけない」理由を説明できますか?

リスト以外で key を使うべき場面をご存じですか?

今回は React の key を適切に扱えないと起こる問題を紹介します。

ダメな例のデモ

まず、key を適切に設定していない、keyをつけるべき場面を実際にご覧ください。

問題1: key をつけるべきなのにつけていない codesandbox.io

問題2: key を適切に設定していない(index で設定してしまっている) codesandbox.io

問題1: key をつけるべきなのにつけていない

recursing-fermi-6bm9c - CodeSandbox

確認手順:

  1. 「change」ボタンをクリックする
  2. 色名がすぐに Green へ変化する
  3. 画像のほうは以前のものがしばらく(新しい画像の読み込みが終わるまで)表示され続ける

このように色名と画像がズレるのは意図していません。

どうして起きるのか?

change ボタンを押したとき React からすると「img の src が変わっただけ」に見えます。 そのため、React は同じ img 要素を使って src だけ変えます。同じ img 要素なので、以前の画像がキャッシュされ、新しい画像を読み込むまで古い画像を表示し続けます。

解決方法: key を設定する

解決するには、React へ img 要素を新しい img 要素で置き換えるよう指示 すれば OK です。そして、ここで使うのが key prop です。key を使えば React に「img 要素が新しくなった」と伝えられます。新しい画像 URL がセットされた新しい img が追加されれば、古い画像が表示されることはありません。

問題2: key を適切に設定していない

zealous-lehmann-luycv - CodeSandbox

こちらは key に配列の添え字を渡してしまっているパターンです。要素を削除したときに問題が起こっています。

確認手順:

  1. 1つ目の delete ボタンを押す
  2. input の値が Blue のままになっている

どうして起きるのか?

これも先ほどの例と同じで、要素が削除されても React からすると「最後の要素が削除された」ように見えるため、1つ目の DOM を使いまわそうとするためです。

解決方法: 要素ごとにユニークな値を key にする

これを解決するには、要素ごとにユニークな値を使えば OK です。key は「ある要素と DOM の対応付けをしている」と考えれば腑に落ちるでしょう(間違えた例では index が同じなのだから input の値が変わらないのは当然)。

まとめ: コンポーネントが内部に状態を持っているときは key に気を付ける

見てきた例は2つとも、コンポーネントが内部に状態を持っていた(img と input)のが原因でした。内部の状態を引き継がせたくない場合は、しっかりと key を設定しましょう。

(もちろん各人が作った React コンポーネントも内部に状態を持っていれば同じような問題が起こります)

useLayoutEffectとは?何ができるの?

対象読者: 「useEffectより早く発火するやつでしょ?」くらいのふんわりとした理解をしている方

useLayoutEffect とは何か?

まずズバリ結論から言うと、「ブラウザが要素をレイアウトしたあと、画面に描画する前に同期的にJSを実行するためのフック」です。

さっぱりわからないと思うので順を追って説明します。

ブラウザのレンダリングの流れ

useLayoutEffect の動作を知るには、ブラウザのレンダリング処理について知らなければなりません。

ブラウザのレンダリングはおおむね次のような流れです。

  1. DOM が変更される
  2. レンダリングツリーを構築
  3. レンダリングツリーをもとにそれぞれの要素の位置と大きさを計算(Layout)
  4. 描画内容を計算(Paint)
  5. Paint した内容を合成(Composite)
  6. ユーザーの画面に実際に反映

このように、ユーザーに見えるようになるまでに複数の工程があります。

useLayoutEffect はいつ実行されるか?

useLayoutEffect は React がコンポーネントをレンダリングして、それを元にDOM を変更して、ブラウザが Layout したあとに実行されます。つまり要素の大きさと位置の情報は取れますがユーザーには見えていない段階です。

(引用: hook-flow)

useLayoutEffect がチラつき抑制になるのはなぜ?

よく useEffect だとチラつくから useLayoutEffect を使うという説明があります。ここまでの説明でなぜチラつきを抑えられるかも説明ができます。

もし、useLayoutEffect をした結果 DOM が変更になったらどうなるでしょうか?答えは Paint が行われず、Layout から再実行される です。ユーザーには useLayoutEffect が実行されたあとの画面しか見えません。そのため変更前の画面はユーザーに見えません。

useEffect は画面に反映された後に実行され、再度 Layout → Paint が行われるためチラつくのです。

useLayoutEffect が同期的とはどういうことか?

Paint は Layout のあと、JS の実行が止まり次第走ります。つまり同期的処理は終わるまで Paint をブロッキングします。逆に言えば非同期的処理は Paint をブロッキングしません。そのため同期処的理でなければなりません。

参考

https://leap-in.com/ja/lets-learn-how-to-browser-works/ https://blog.isquaredsoftware.com/2020/05/blogged-answers-a-mostly-complete-guide-to-react-rendering-behavior/#render-behavior-edge-cases https://ja.reactjs.org/docs/hooks-reference.html#uselayouteffect

2021年を振り返る

今年は入社2年目ということで色々あったので書きたい。

  • チーム内のフロントリードを任された
  • リーダブルコードを意識してコーディングしてた
  • 開発環境の整備とか開発フローの改善の提案をしたり、実際に改善したりした
  • 外部登壇はほぼしなかった
  • 趣味でプログラミングする機会が減ってきた
  • テキストベースコミュニケーションをひたすら意識してた

チームにフロントエンド、サーバー、QAといて、フロントエンドが2人(俺と新卒)なのでフロントの部分は任される形になった。けど、スケジューリング能力の欠如やらでなかなか上手くできない…来年こそはしっかりやりたいな。

けどそもそも2年目でリード任されるのが早すぎる気がする。フロントエンド自体が平均年齢低めだから仕方ないとはいえ、早くない…?

あとはリーダブルコードをひたすら意識して書いてた。難しい問題をなるべく簡単に解く、変数の命名をしっかり意識する、意味あるテストを書くとか。だから俺の書いた部分はかなり読みやすい自信がある…と言い切りたいがそうでもない箇所もあるな。来年も引き続きがんばりたい部分。

業務と直接関係のない改善とかもたくさんやった。CircleCIのワークフローを見直したり、設計フローを見直したり、チームで使ってるslack botの改善したり。こういう自由を許されてるのはありがたい(下手したらサボりと見做されかねないからね)。

外部登壇は今年はほぼやらなかった。理由は単純で、自発的でない登壇は向いてないと思ったから。来年は自発的に登壇してみたいな。なんかテーマあれば。

趣味でプログラミングする時間はやっぱ減ってきた。けど、最近はスモールチーム内のフロントリードしてる関係でコミュニケーション系の仕事ばっかで仕事でプログラミングする時間も減ってきてる。来年は趣味の方である程度まかないたい。

来年の目標とかやりたいこと

  • とりあえず現職でもっとしっかりリードできるようなりたい
  • web vitals 意識して開発したい
  • 開発確認をもっとしっかりやってQAさんの負担減らしたい(てか今の俺があまりに雑)
  • 仕事に慣れてきたけど、どうしてもやることがワンパターン(JSON色つけ係)だから、データベースとかedge workerとか他のことやりたい

この辺かな。転職は考えてないので大きくは変わらない気がする。