LoginSignup
11
1

【React】コンポーネント内での直DOM操作はなぜいけないかを理解したい

Last updated at Posted at 2023-12-17

ダメなパターン

ReactでDOMを操作したいときに、document.getElementByIddocument.querySelectorなどを使うことは推奨されていません:no_good:

export const Form = ()=> {
	const inputElement = document.getElementById('myInput')
	const handleClick = () => inputElement.focus()
	return (
		<>
			<input id="myInput" />
			<button onClick={handleClick}>Focus the input</button>
		</>
	)
}

なぜダメか

仮想DOMによる差分更新が破綻してしまい、宣言的UIの思想に反するからです。

〜 完 〜

そもそも…

宣言的UIってなんだっけ?:thinking:

宣言的UIは、初めに目的のUIの形を宣言し、それに基づいて処理が実行されるというアプローチです。
命令的UIと比較するとわかりやすいです。

TODOアプリを例にして考えてみます:page_facing_up:
TODOを追加したらリストにチェックボックスと文言、削除ボタンが生成されます。
スクリーンショット 2023-12-22 10.57.53.png

命令的UI(例:jQuery)では、生成されるDOMを順番に命令していきます。
命令的な書き方は順序通りに書くことができますが、最終的にどのようなDOMが生成されるかを想像することが難しいです。
一方、Reactなどの宣言的UIでは、最終的なDOMの形を先に宣言し、値や情報を渡すことでUIを構築します。
これにより、最終的なUIがどのようなものになるかをより明確に理解することができます。

宣言的UIの思想では、DOMを直接操作したり生成したりせずに、UIの形を宣言することが大切です!

仮想DOMってなんだっけ?:thinking:

仮想DOMは、実際のDOMをレンダリングする前に、仮想のDOMの構造を計算することで、高速な表示を実現する手法です。

スクリーンショット 2023-12-17 22.42.46.png

そして、この仮想DOMの生成はReactの視点から行われます。
Reactの外部で直接DOMを操作すると、仮想DOMの生成の対象外になり、変更が正しく検知されなくなってしまいます。

つまり?

  • 直接的なDOM操作を使用すると、Reactの仕組みをバイパスしてしまい、コンポーネントの状態とDOMが同期しなくなる可能性があること
  • 宣言的にUIを構成することで、Reactのメリットである最終的なUIのイメージが明確になること

上記のような点から、Reactで直接DOM操作を行うことは推奨されません。

どうすればいいか

ReactでDOMにアクセスする時はuseRefを使います。
Reactが提供する手段によってDOM操作を行うことで、上記の懸念を解消できます。

export const Form = ()=> {
	const inputRef = useRef(null)
	const handleClick = () => inputRef.current?.focus()
	return (
		<>
			<input ref={inputRef} />
			<button onClick={handleClick}>Focus the input</button>
		</>
	)
}

ただし、公式ドキュメントでも説明されているように、refは最終手段として使用するべきです。
可能な限りDOMを操作せずに問題を解決する方法を考えるようにしましょう。

11
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
1