📘

React公式ドキュメントの学習振り返り

2024/03/27に公開

はじめに

ReactのドキュメントのLearnのページを読みましたので見返せるように振り返ります。

現在Next.jsアプリのプロジェクトで稼働しており、既存実装を参考にとりあえず動くコードを書くことはできるようになってきたものの、そもそもReactについてよく知らないまま開発しているという状況でした。この状況からの脱却を目指して、ドキュメントを1から読みました。

やったこと

公式ドキュメントのLearnのページのうち、「インストール」以外の項目を読みました。
チュートリアル・チャレンジ問題で実際に手を動かすこともできました。

理解できていなかったこと/改めて学習できたこと

Reactを学ぶ」の4つのセクションの項目に沿って、理解できていなかったこと/改めて学習できたことを黄色い枠中に、その下に自分の理解・感想等を書きます。

UI の記述

はじめてのコンポーネント

コンポーネントが「マークアップを添えることができる JavaScript 関数」であるという見方はしたことがなく、固有の書き方と思い込んでいました。
意識したことがありませんでしたが、確かにコンポーネントを定義するときは以下のようにJavaScript関数の形式で定義していました。
JavaScript関数だと思って改めてコンポーネントのコードを見返すと、これまでよりスッキリ理解できそうです。

export function MyComponent() {
  return (
    <div></div>
     );
}

コンポーネントに props を渡す

プロジェクト参画当初は、なぜ明示的に渡しているpropsとそうでないchildrenがあるのかと混乱していました。今回改めて理解できたため、今後混乱することはなくなりそうです。

条件付きレンダー

これはReactというよりJavaScriptの話とは思いますが、このミスはどこかでしそうなので忘れないようにします。

コンポーネントを純粋に保つ

純関数という言葉を知らず、コンポーネントとイベントハンドラが純粋かどうかを意識したことがありませんでした。
ドキュメントを読んでいる分には理解できましたが、自分で書けるのかとなると自信がないので訓練が必要そうです。日々の開発でコンポーネントが純関数になっているか意識することから始めようと思います。

UI をツリーとして理解する

この2つのツリーについては理解しきれていないですが、以下のメリットがあるものと理解しました。

  • レンダーツリー
    • どのコンポーネントがどのコンポーネントの中に入っているかが視覚的に分かるため、コンポーネントの配置が理解しやすくなる。
  • 依存関係ツリー
    • 特定のモジュールが他のモジュールに依存しているかどうかが分かるため、コードの変更や修正を行う際に影響を受ける部分を考慮しやすくなる。

インタラクティビティの追加

state:コンポーネントのメモリ

知っているようできちんとは理解できていないことでした。コンポーネントの再利用性を保つために重要な特性だと理解しました。

レンダーとコミット

「Reactのレンダリング = 画面の際描画」程度の認識しか持っていなかったため、上記のステップで画面更新が行われていることを理解できてよかったです。

stateはスナップショットである

カウンターの例を見て、stateの更新が非同期的であることが理解できました。直感的にはまだnumberが3になると思えてしまうので、自分で実装する際にも注意します。

一連の state の更新をキューに入れる

更新用関数を用いることで、不要な再レンダリングを避けながら複数回stateを更新することができるということだと理解しました。

state内のオブジェクトの更新

Immerは便利そうと思う反面、提供されている関数について学習する必要があるのと、使うことに慣れる内にこれが何をしてくれているものなのか分からなくなってしまうのではないか、と想像してしまいました。  
通常の方法で更新を行なったりstateの持ち方を工夫したりすることでミューテーションが起きないようにしたいと思いました。

state 内の配列の更新

オブジェクトも配列も新しいものを作成してセットする必要があることを理解できました。

stateの管理

state を使って入力に反応する

Reactが宣言型プログラミングであること、そもそも宣言型/命令型とはどういうことなのか理解できました。
また、Reactが命令型プログラミングでUIを操作する際の問題を解決するために作られたものということを知りました。
※問題:様々なフォームでたくさんのページを更新する操作を命令的に実装する(インタラクションに応じてUIを操作するための命令を実装する)場合を考えた時、新しいUI要素や新しい操作方法を追加する際に、既存のすべてのコードを注意深くチェックして、バグ(例えば、何かを表示または非表示にすることを忘れていないか)を確認する必要がある。

state 構造の選択

ドキュメント中のサンプルコードを見て、firstNameとlastNameがあったらfullNameは自分で計算できる、ということくらいは気づけそうと思いましたが、同時に2つのstateの更新が必要な場合に起こりうるstateの矛盾・stateのリストの要素の内の一つを別でstateに持つ場合に起こりうるstateの重複は注意しないとやってしまいそうと思いました。
複数のstateを定義する際はこのページに戻ってこようと思います。

コンポーネント間で state を共有する

共通の親に移動させることをstateのリフトアップと呼ぶことは知りませんでした。また、このリフトアップは無意識で行なっていましたが、コンポーネントをprops駆動にするか、state駆動にするかという観点で考えればいいというのは納得感がありました。

state の保持とリセット

条件分岐の際、stateを保持したいにもかかわらず、スタイルを適用したい等の理由で以下のようにdivを挟んで(isPlayerAがfalseの場合)stateが保持されなくなってしまうということはやってしまいそうと想像できたため注意します。

export default function Scoreboard() {
  const [isPlayerA, setIsPlayerA] = useState(true);
  return (
    <div>
      {isPlayerA ? (
        <Counter key="Taylor" person="Taylor" />
      ) : (
        <div className="notPlayerA"> 
          <Counter key="Sarah" person="Sarah" />
        </div>
      )}
      <button onClick={() => {
        setIsPlayerA(!isPlayerA);
      }}>
        Next player!
      </button>
    </div>
  );
}

state ロジックをリデューサに抽出する

リデューサはこれまで知らなかったフックで、少しとっつきにくい印象を受けました。私のような初学者やリデューサに馴染みのない方にとっては少し学習コストがかかるように感じました。
ただリデューサを使うことで、複雑なstateの管理をする際には保守性が上がりそうと感じました。

コンテクストで深くデータを受け渡す・リデューサとコンテクストでスケールアップ

コンテクストも知っているだけで使ったことのないフックで、少し難解に感じました。ただ、ドキュメントを読んで理解できなかった箇所はなく、用途例の「テーマ」や「現在のアカウント」はコンテクストを使いたいと思わせてくれました。
リデューサとコンテクストの組み合わせも難解で、実際のプロジェクトで使ってみて慣れることが必要と感じました。

避難ハッチ

ref で値を参照する・ref で DOM を操作する

refも使ったことがありません。ほとんどの場合、DOM 要素を保持するために使用するということなので、今後フォーカスやスクロール、要素の測定など、UIを変更しない操作に使用することで理解したいです。

エフェクトを使って同期を行う

Effectも使ったことがありませんでした。これも使わないことにはなかなか理解しきれない印象を受けたため、例えばページがロードされた後、株価情報や天気予報などのデータを定期的な間隔でサーバーから取得して表示を更新するようなアプリを作成してみるのがいいのではないかと思いました。

そのエフェクトは不要かも

この章は比較的理解しやすかったです。useMemoは使いやすいと感じたため取り入れたいと思いましたが、実際にuseMemoを利用した最適化が力を発揮するのは、「useMemo で行う計算が著しく遅く、かつ、その依存値がほとんど変化しない場合」というほんの一部のケースに限られるそうなので、使う機会はそう多くなさそうです。

感想

Reactの機能やコンセプトについて順を追って学習することができてよかったです。
実際に動くサンプルを触ることができたり、そのコードを編集したりできたりしたことと、項目ごとにチャレンジ問題が用意されていたことで理解が深まったと思います。

また、リデューサやコンテクストのような、普段の開発ではあまり登場頻度が多くないフックも、適している場面に遭遇した際に使えるようにするために学習を進めたいと思いました。

終わりに

今回、Reactについてよく知らないまま開発しているという状況からの脱却が目的でしたが、正直「脱却できました。」とは言い切れないです。ただ、コンポーネントやstateといった基本的なことに対しての理解は以前より間違いなく深くなったので、読んでよかったですし、引き続き学習を進める意欲も湧きました。

理解できていなかったこと/改めて学習できたことの粒度やコメントの書き方にバラつきはありますが、学習記録として残せたのはよかったと思います。

参考資料

https://ja.react.dev/learn

Discussion