【第9回】Reactが何を代わりにやっているのかが分かる|DOM操作(嫁子が教えるTS講座)

今回のゴール

前回(非同期処理)までは、実行しても文字が出るだけでした。今回から画面が動きます。全体の流れは講座の目次へ。


嫁子: 今日でようやく「作ってる感」が出るよ。ここまでずっと console.log だったからね。

ただし正直に言っておくと、今日のやり方は、第4部でReactに置き換わるの。じゃあ無駄かというと逆で、Reactが何をラクにしてくれているのかは、この面倒くささを知らないと分からないんだよ。

「昔はこうやってたのか」を1回だけ体験する回、くらいに思っててね。


① DOMとは何か

ブラウザはHTMLを読み込むと、それを操作できる形に変換してメモリ上に持ちます。これがDOM(ドム)です。

第1回で「ブラウザがHTMLを解釈して画面を作る」という話をしましたが、その解釈した結果が置いてある場所だと考えてください。

JavaScriptから触るのは、HTMLファイルそのものではなくDOMです。だからファイルを書き換えなくても、画面だけを変えられます。


② 用意するファイル

HTMLとJavaScriptを1つのフォルダに置きます。

<!doctype html>
<html lang="ja">
<body>
  <h1 id="title">こんにちは</h1>
  <button id="btn">押す</button>
  <script src="app.js"></script>
</body>
</html>

id は目印です。JavaScriptから探すときに使います。

<script src="app.js"> は「このJavaScriptを読み込んで実行して」という指定です。</body> の直前に置きます。先に書くと、まだ存在しないHTMLを探しに行ってエラーになります。


③ 要素を取ってきて、書き換える

const title = document.getElementById("title");
title.textContent = "書き換えました";

getElementById は「この id の要素を探して持ってくる」という命令です。取ってきた要素の textContent に代入すると、画面の文字がその場で変わります。

よく使うものだけ挙げておきます。

書き方 すること
textContent 文字を書き換える
value 入力欄の中身を取る・入れる
classList.add("done") CSSのクラスを足す(見た目を変える)
style.color = "red" 直接スタイルを変える

嫁子: innerHTML っていうのも見かけると思うけど、あれはHTMLごと差し込める分、危ないの。

外部から来た文字をそのまま入れると、悪意のあるコードを実行させられることがあるんだよ。だから文字を入れたいだけなら textContent を使ってね。AIが innerHTML を使っていたら、そこは一度立ち止まるといいよ。


④ ボタンを押したときに動かす

「クリックされたら実行する」を登録します。

const btn = document.getElementById("btn");

btn.addEventListener("click", () => {
  title.textContent = "押されました";
});

addEventListener は「この出来事が起きたら、この関数を実行して」という登録です。第7回でやったアロー関数が、ここで出てきます。

登録した時点では実行されず、クリックされたときに初めて動きます。第7回の最後に書いた「addTaxaddTax() は別物」という話が、まさにここで効いてきます。

btn.addEventListener("click", doSomething());  // ✕ 読み込んだ瞬間に実行される
btn.addEventListener("click", doSomething);    // ○ クリック時に実行される

嫁子: 括弧をつけると、その場で実行した結果を登録することになるの。だから「ページを開いた瞬間に動いてしまう」ってなるんだね。

括弧なしなら、関数そのものを預けることになる。「あとでこれをやって」と渡すか、「今やった結果」を渡すかの違いだよ。


⑤ 入力を受け取る

入力欄の中身は value で取れます。

<input id="name" type="text">
<button id="add">追加</button>
<p id="result"></p>
const input = document.getElementById("name");
const result = document.getElementById("result");

document.getElementById("add").addEventListener("click", () => {
  result.textContent = input.value + " を追加しました";
});

ここで第4回の話を思い出してください。input.value は必ず文字列です。数値を入力しても文字列で届くので、計算に使うなら Number(input.value) で変換します。

嫁子: 第4回で「フォームの数字は文字列で届く」って言ったの、覚えてる? ここがその現場だよ。

個数を足したつもりが "11" になるやつね。この事故を型で防ぐのが、次の第3部なの。だんだんつながってきたでしょ。


⑥ この書き方の限界

ここまでで画面は動かせます。ただ、規模が大きくなると急につらくなります。

Reactのようなフレームワークは、この「どこを書き換えるか」を自動でやってくれます。データを変えれば画面が追従する、という形に変わります。

嫁子: だから第4部に入ると、getElementById はほぼ書かなくなるの。

でも今日やったことが無駄になるわけじゃないよ。Reactが裏でやっているのは、結局これだからね。中で何が起きているか想像できる人と、魔法だと思ってる人では、詰まったときの強さが全然違うよ。


つまずきポイント

null が出たら、id が合っていません。存在しない id を指定すると null が返り、その先で「nulltextContent は読めません」というエラーになります。打ち間違いか、<script> を書く位置が早すぎるかのどちらかです。

確認はブラウザの開発者ツールで。F12キー(Macは Cmd + Option + I)で開き、Consoleタブに console.log の結果とエラーが出ます。エラーの文面はそのままAIに貼れば伝わります。


今回のまとめ


次にやること

次回は第2部の総合演習、買い物メモアプリです。ここまでに出てきたものを全部使って、実際に動くものを1つ作ります。

今回の宿題:上のHTMLとJavaScriptを作って、ボタンを押すと文字が変わるところまで確認してください。自分の書いたコードで画面が動くのは、ここが初めてになります。

嫁子: 動いた瞬間、けっこう嬉しいと思うよ。第1回から数えて9回目だからね。

AIに全部作らせてもいいんだけど、この回だけは自分で打ってみてほしいな。ここまで読んできたものが1つにつながる感覚は、読むだけだと出てこないから。