TL;DR
- UIは状態から一意に決まる
- 厳密には「UI = f(props, state, context)」と考えるのが正確
- Reactは「state → UI」変換を自動でやる仕組み
はじめに
Reactを調べていると「UI = f(state)」という表現を目にすることがある。
なんとなく理解はしているものの、人に説明できるかと言われると、
真っ直ぐな目で「Yes!!」とは言えないので、改めて文章にして整理する。
f(state) とは
ここでいう f は、state(や props)を受け取って UI を返す計算を指す。
function Counter({ count }: { count: number }) {
return <span>{count}</span>
}
この関数は、
- 外部の状態を変更しない
- 同じ
countを渡せば、常に同じ UI を返す
という意味で、純粋な計算
React以前(命令的 UI)
button.addEventListener('click', () => {
count++
document.querySelector('#count').textContent = count
if (count > 10) {
document.querySelector('#warning').style.display = 'block'
}
})
この書き方では、次のような問題が起きやすい。
- 状態とUIが分離していない
(状態がDOMに分散して保存されている) - UIを更新し忘れるとすぐに不整合が起きる
- 「今どういう状態なのか」をDOMを見ないと判断できない
DOMが表示だけでなく状態の保存場所にもなってしまうのが問題点。
Reactの宣言的UI
function Counter() {
const [count, setCount] = useState(0)
return (
<>
<span>{count}</span>
{count > 10 && <Warning />}
<button onClick={() => setCount(c => c + 1)}>+</button>
</>
)
}
このコードでは、
- UIは常に
countの値から計算される - 「10を超えたら表示する」は条件として宣言されている
- 表示・非表示を自分で切り替えていない
結果として、
state が変わるだけで UI は自動的に正しくなる
という状態が実現されている。
厳密には「UI = f(props, state, context)」
実際のReactコンポーネントは、state だけでなく
- props
- context
なども入力として受け取る。
そのため、より正確に書くなら次のように表現できる。
UI = f(props, state, context)
Reactはこれらの入力が変わるたびに render を再実行し、
UIを毎回計算し直すことで、表示の整合性を保っている。
まとめ
- ReactではUIを直接操作しない
- UIは「現在の状態」から毎回計算される
- この考え方を一言で表したものが「UI = f(state)」
「DOMをどう更新するか」ではなく、
「この状態ならどう表示されるべきか」を書く。