Open5

Reactドキュメントまとめ

RyoheiRyohei

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

https://ja.react.dev/learn/keeping-components-pure

目次
  • 純粋
  • 不純 (impure)
  • 純粋と不純 (impure) まとめ
  • ミューテーションと純関数
  • 副作用

純粋

関数型プログラミングにおいて、純関数とは次の特徴がある。

  • 自分の仕事に集中する: 呼び出される前に存在していたオブジェクトや変数を変更しない。
  • 同じ入力には同じ出力: 同じ入力を与えると、純関数は常に同じ結果を返す。

そして、React のレンダープロセスは常に純粋である必要があります。
(コンポーネントは JSX を返すだけであり、レンダー前に存在していたオブジェクトや変数を書き換えしない)

不純 (impure)

上の特徴を満たしていない物は純関数とは言えません。

let guest = 0;
function Cup() {
  // Bad: changing a preexisting variable!
  guest = guest + 1;
  return <h2>Tea cup for guest #{guest}</h2>;
}

export default function TeaSet() {
  return (
    <>
      <Cup />
      <Cup />
      <Cup />
    </>
  );
}
条件を満たしていないもの。

純粋と不純 (impure) まとめ

基本的にコンポーネントは自分のことだけを考えなければいけない。
「どの順番でレンダーされるか」「外部の変数は今なにか」
この様に自分の仕事に集中せず、同じ入力には同じ出力を返さない物は純粋とは言えない。

ミューテーションと純関数

関数のスコープ外の変数や、呼び出し前に作成されたオブジェクトをミューテートする関数は純関数とは言えない。(参照型の変数について,参照先のオブジェクトに変更を加えること)

immutableとmutable

  • immutable(書き換え不可、元の値が変わらない、オブジェクト配列以外(プリミティブな型)、参照先が変わる)
    -元の値が書き換わると言うよりも、メモリに新しいところが登録されると言うこと。
  • mutable(書き換え可能、参照先はオブジェクト自体、配列自体である。)
    • 変数からの参照は{}自体だから、中身だけが変わる。

function Cup({ guest }) {
  return <h2>Tea cup for guest #{guest}</h2>;
}

export default function TeaGathering() {
  let cups = [];
  for (let i = 1; i <= 12; i++) {
    cups.push(<Cup key={i} guest={i} />);
  }
  return cups;
}

TeaGathering関数の外でcupsが作られていた場合は純関数とは言えないが、この場合は関数内での変化のためTeaGathering関数は純関数と言える。
レンダー中にその場で作成した変数やオブジェクトであれば、書き換えることは全く問題ない。

副作用

関数型プログラミングには純関数が重要であるとは言え、副作用は必要になります。ここで言う副作用とは、外部通信やアニメーションの開始などです。
React では、副作用は通常、イベントハンドラの中に属します。
ボタンをクリックした時にAPIを叩くなどはよくあることだと思います。
つまり、、イベントハンドラは純粋である必要はありません。

RyoheiRyohei

前提、別スクラップで純粋性については書いている。
https://zenn.dev/link/comments/dd1f35092b274e

React はなぜ純粋性を重視するのか?

ドキュメントの最後の方にトグル形式3つ重要なことが書いていたのでそれをまとめる。

目次
  • 環境に依存しない
  • パフォーマンスを向上1
  • パフォーマンスを向上 2

環境に依存しない

コンポーネントが異なる環境、例えばサーバ上でも実行できるようになります! 入力値が同じなら同じ結果を返すので、ひとつのコンポーネントが多数のユーザリクエストを処理できます。

どんな環境でも純関数は同じ入力(引数)には同じ出力(戻り値)であると、どの環境でも同じ様な結果を出力することができる。

function add(a, b) {
  return a + b;
}

パフォーマンスを向上1

入力値が変化しない場合、レンダーをスキップすることでパフォーマンスを向上できます。これが問題ないのは、純関数は常に同じ出力を返すため安全にキャッシュできるからです。

これはmemo化で役に立ちます。memo化を行う時にuseMemoやuseCallbackを使うと思います。しかしuseMemoを使うからパフォーマンスが向上すると言う訳ではありません。
前提としてその関数が純関数でなければいけません。

パフォーマンスを向上2

深いコンポーネントツリーのレンダーの途中でデータが変化した場合、React は既に古くなったレンダー処理を最後まで終わらせるような無駄を省き、新しいレンダーを開始できます。純粋性のおかげで、いつ計算を中断しても問題ありません。

Reactは仮想DOM(Virtual DOM)を使って効率的にUIをレンダーします。仮想DOMは、UIの現在の状態と更新後の状態を比較し、必要な部分だけを更新することでパフォーマンスを向上させます。

Reactコンポーネントが純粋であれば、そのコンポーネントは常に同じ入力(プロパティや状態)に対して同じ出力(レンダリング結果)を提供するため、途中で値が変わっても関数自体の機能に影響しない。
(例えば、青色の物を入れると必ず赤色にしてくれる箱があるとする。箱が嵐の中、水の中にあったとしてもその機能は変わらず青を赤にしてくれる。純粋関数はこの箱のような物で、途中でデータが変わっても純粋関数である以上結果が変わることはない。)

RyoheiRyohei

レンダーとコミット

Rectのレンダーとコミットについて理解する。
Reactん土台をしっかり固めることで、これからやる応用に適応させるため。