関心の分離(React)
正直わからん(今見ても全然わからん)
関心(何をしたいのか)ごとに分離して実装すること
ライフサイクルメソッド
o 時間で分離している(when init, when terminate, when update, when rendering etc)
x 機能で分離していない(時間による分離を選んでいるので、当たり前だが機能軸では分離されてない)
Reactのhook
o 機能で分離している(C言語マクロ的な仕組みで useState() とか useEffects() みたいなのを定義できるので、関数呼び出しの書き方だけで「状態の定義」「状態変更処理の定義」などができる → 手続き的に関連処理を全部一箇所に定義できる)
x 時間で分離していない(プログラマに意識させない。ライフサイクルはReact側がよしなにやるってこと?sta.icon)
---
タイマー2つによるカウントダウンUI
普通(ライフサイクルメソッド)の場合、
o 時間で分離している(when init, when terminate, when update, when rendering etc)
x 機能で分離していない(時間による分離を選んでいるので、当たり前だが機能軸では分離されてない)
reactのhook
え、コード見ても全くわからん。おまじない?sta.icon
ボリュームエグすぎない?w
解読して戻ってきたsta.icon
で、reactのhookだと何が嬉しいねん?
そこでReactでは機能的凝集度を高めるhookと名付けられた機能を導入した。
そうですか
hookはライフサイクルメソッドのようなclass interface実装ではなく、関数の暗示的状態(非透過的な参照)を利用している。
暗示的状態、は筆者の意味不明な言葉遣いなので虫
非透過的な参照?
ある式が参照透過であるとは、その式をその式の値に置き換えてもプログラムの振る舞いが変わらない
値渡しと参照渡し?……ではない雰囲気sta.icon
え?意味わかんね?冪等性のこと言ってる?sta.icon
普通はlet x=3; (ごにょごにょ); console.log(x);をすると、xの値はわからん
途中で書き換えてる可能性があるから
でも参照投下だと =3 が保証されてるらしいよsta.icon
constしか使えまテンってことかsta.icon
つまり関数がconst的である、みたいなことが言いたいわけやな
ああ、少しわかったかもsta.icon
計算結果をreturnするんじゃなくて、「計算を行う関数」をreturnしている
で、その内部ではuseStateみたいなC言語マクロみたいな仕組みでごにょごにょできる
結果として、「ごにょごにょを行える関数」をreturnしている
実質インスタンスをnewしている、みたいなことができている
コンポーネントあたり1つしか持てないライフサイクルメソッドと異なり、関数であるhookは何度でも利用ができる。
そうですね
また各hook関数が状態の保持やライフルサイクルの管理といった個別機能を持つため、機能Aに必要なすべてのhookを1箇所に集めることができる。
単にhook関数呼べばいいだけだもんね
すなわち機能的凝集度が高い状態、機能的なSoCが実現できる。
そうですね
要するにuseState()みたいなC言語マクロ的な仕組みがあることで、本来methodとして定義すべき処理を「関数の中で関数呼び出しを書く」という営為で定義できる
✅ちょっと解読
0
code:original.jsx
function Clock() {
useEffect(()=>{
const id = setInterval(() => setCountA(n=>n+1), 1000);
return ()=> clearInterval(id)
}, []);
useEffect(()=>{
const id = setInterval(() => setCountB(n=>n+1), 1000);
return ()=> clearInterval(id)
}, []);
return <div>now count: A/{countA} - B/{countB}</div>
}
1
code:jsx
function Clock() {
useEffect(func, []);
useEffect(func, []);
return <div>now count: A/{countA} - B/{countB}</div>
}
code:func.jsx
()=>{
const id = setInterval(func2, 1000);
return ()=> clearInterval(id)
}
code:func2.jsx
() => setCountA(n=>n+1)
✅まず countA が数字で、setcountA が関数になっている理由がわからん
どっちもconstで定義してるだろうが
useState()の戻り値? →yes
code:jsx
const updateFunction = () => {
stateを更新する関数(stateの演算など);
};
stateを更新する関数(stateの演算など); という書き方で、stateを演算できちゃうわけねsta.icon
ああ、そうか
jsxという世界を採用しているから、「いやこれC言語のマクロレベルの能力ないと実装できんだろ。jsだけでは実装無理やろ」にはならんわけなsta.icon
というか、これをやりたかったからJSXってのを新たにこしらえたのかな? funcは1秒ごとにインクリメントしたいだけ
✅funcの中身もよーわからんな
returnは「関数」を返してるよね
なんかいちいち値ではなく関数を指定しているのがんん?って感じ
とりあえずuseEffect()見てみる
第一引数にレンダリングされるタイミングで実行したい関数を指定します。
sta.icon「第一引数に『レンダリングされるタイミングで』『実行したい』関数を指定します」
第二引数には何も指定しません。
wikipediaでは, [])があるけど?
たぶんミスだろsta.icon
↑公式でもuseEffect(didUpdate);ってあるし
returnでクリーンアップしたい処理を指定します。(なければreturnブロックは不要)
returnの中でクリーンアップって、全然直感的じゃなくて意味わかんねsta.icon*2
jsの仕様頭に入れて読み解いて「あー、たしかにクリーンアップ時に実行される挙動になってるね」まで理解しなきゃダメ?
code:jsx
useEffect(() => {
console.log('レンダーされました。');
return () => {
// clean up処理を記述する。
console.log('クリーンアップします。');
};
});
code:2.jsx
useEffect(() => {
レンダー時に実行したい処理
return クリーンアップ処理
});
code:3.js
function 処理(){
レンダー時に実行したい処理
return クリーンアップ処理
}
useEffect(処理);
処理を呼び出すと、レンダー時に実行したい処理が呼び出される
で、「クリーンアップ処理を行う関数」がreturnされる
この時点ではクリーンアップ処理はまだ行われない
ああ、そうか、関数を返させることで、呼び出し元で「処理を保持する(まだ実行はしねぇよ?)」ができるわけかsta.icon
本来、こんな内部的な事情を利用者に関与させるべきではないが、jsの仕様で難しいので、仕方なく「returnの中にクリーンアップ書け」という「直感的でないクソわかりづらい」制約を課している。
わかりづらくて嫌なんだけど……
ワーキングメモリゴリゴリ使うからねぇ……
GoやTSをはじめコンパイル型言語再び注目されてるけど、やっぱりプログラマってワーキングメモリおばけで「手元で管理したい」なんかなー
まあReactは本質的には「ここにこういうこれを書け!」とルール化しているだけ、内部でなんでコレで動くかなんて気にせず機械的に従うのが利口な気もするけどsta.icon*2
wikipediaのコードは理解した
useState、useEffectみたいなマクロ構文みたいな奴のおかげで、状態定義や状態変更処理をその場でサクっと書ける
jsにおいて、処理の記述はアロー記法なので、アロー記法で書いてる