rempei
@rempei

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Cannot read properties of null のエラー

Q&A

Closed

解決したいこと

Javaでブラックジャックを作ってみたのですが
次はJavaScriptで作ってみようと思い挑戦しています。

解決したいことは以下のエラーです。
クリックするとプレイヤーの手札ゾーンにカードが追加されるfunctionを作ってみたのですが上手くいきません。

どなたかこの愚か者に知恵をお貸しください。

発生している問題・エラー

Uncaught TypeError: Cannot read properties of null (reading 'appendChild');

<div className="player">プレイヤー
    <div className="player_hands"></div>
    <button className="draw" type="button" onClick={createCard()}>ドロー</button>
</div>

createCard()

function createCard() {
  const newCard = document.createElement("input");
  newCard.type = "text";
  newCard.className = "card";
  document.querySelector(".player_hands").appendChild(newCard);
}

自分で試したこと

ここに問題・エラーに対して試したことを記載してください。

0

3Answer

Wrong
<button className="draw" type="button" onClick={createCard()}>ドロー</button>
                                                ^

この書き方は即時に関数を呼び出します.
Reactの場合onClickには呼び出される関数のオブジェクトを渡さなければなりません.

Correct
<button className="draw" type="button" onClick={createCard}>ドロー</button>

ただそれ以前に今回はReactですので,もっとコンポーネントフルな設計をすべきかと思われます.
特にdocument.appendChildを直接Reactのコンポーネント内に使用することは,Reactのライフサイクルを無視することになりますので,可能な限りコンポーネントを組み合わせた設計を行ってください.

察するにJavaで書いていた時からあんまりオブジェクト指向的な書き方(特に,役割や責任の分担)ができていないのではないかと思われますので,今一度ちゃんと学んでみることをお勧めします.
今回はブラックジャックですので,ゲームマスター(勝敗管理)→プレイヤー(手札・点数の管理)→カードといった風に,それぞれが持つ役割と上下関係をモデリングできると考えられます.

2Like

Comments

  1. 具体的にどう設計するかですが,Reactの公式チュートリアルが大変参考になりますので是非読んでみてください.
    〇×ゲームを題材にどのコンポーネントがどのような情報と役割を持つべきかについて説明されています.
    以前の公式チュートリアルはクラスコンポーネントによる実装でしたが,下記ページは関数コンポーネントの書き方で記載されています.

    https://beta.reactjs.org/learn/tutorial-tic-tac-toe
  2. @rempei

    Questioner

    アドバイスありがとうございます。参考にさせていただきます。
    ちなみにReactでquerySelector().appendChild()のようにボタンを押すと
    任意の場所に子要素をつくるのにいい方法はあるでしょうか?
  3. Reactで子要素,子コンポーネントを動的に増減したい場合は,基本的に各要素を管理するための配列か何かをstateに保持してください.詳しくはこれまた公式ドキュメントが参考になります:

    https://beta.reactjs.org/learn/updating-arrays-in-state

    Reactは何をするにもstateを更新しながら動かすのが基本です.
  4. 一応書いておくと,Reactは特に情報の上下関係の面でかなりの独自管理を敷くフレームワークです.
    そのため責任分担が非常に重要となり,querySelectorなぞで任意の要素を見に行くという行為自体がその責任の範疇を超えかねないためにReactの設計思想に反することになります.jQuery的な実装イメージは一旦捨て去ってください.
    表示位置は‪CSSでなんとでもなります.
  5. @rempei

    Questioner

    ありがとうございます。固定観念を一度捨て去り勉強しなおします。

まず使用環境を記載してください.(React/Webpack or Vanilla他)
検証可能な情報さえ揃えれば,より的確な導きが得られるでしょう.

0Like

Comments

  1. @rempei

    Questioner

    Reactです。create-react-app で作った環境です。
    よろしくお願いします。

Uncaught TypeError: Cannot read properties of null (reading 'appendChild');
のエラーはざっくりいうとnullに対してappendChild()ができませんよーということで、
appendChild()をしようとしているdocument.querySelector(".player_hands")の方を見ます。

document.querySelector(".player_hands")自体は特に問題は無いですが、html側を見ると、class="classname"と書くべきところがclassName="classname"のような書き方になっているため、要素の取得ができず、(nullとなってしまい)appendChild()が失敗しているようです。

↓とりあえず直したもの
https://jsfiddle.net/yqrsLcw1/2/

0Like

Comments

  1. @rempei

    Questioner

    ご回答ありがとうございます。
    申し訳ありません、Reactで作っていたので直したものを試してもダメでした。

Your answer might help someone💌