ReactとFirebaseで下記の記事を参考に、ログイン機能を作っていた(というか、Authの実装練習がてら新しくcreate-react-appをした)際に発生したエラーの対処法を説明します。なかなかググっても良さげな答えが日本語、英語ともになかったので、ここで記述しようと思います。
ReactでFirebase Authenticationを使う
同じ状況の人は参考にしてみてください。
エラー内容
エラーメッセージはは以下の通りです。
Error: Target container is not a DOM element.
「ターゲットコンテナはDOM要素では無い?」となったので調べてみることに。
ただ、このエラーに関しての具体的な初心者でもわかるような説明のある記事が、記事冒頭でも言った通りなかったので、firebase関連でいろいろと検索をしていきました。
解決した方法
public(またはbuildなどのディレクトリ)のindex.html
の<body>タグ
内に以下のコードを記述し、それ以外の<body>タグ
内のコードを全て削除(orコメントアウト)する。
<body>
<div id="root"></div>
</body>
解決に至るまでの過程
(検索ワードはうろ覚えですが)エラーメッセージ+firebase
で検索していると下記の記事を発見しました。
「今回はReact+Firebaseだし、関係なさそうだな」と思いつつも、この記事を何となく上からさーっと目を通していくと、sourceという部分に目が止まり、そこを見ていて気付きました。以下に具体的な解決の過程を示します。
過程
firebaseを使う際に、
$ firebase init
でまずは初期設定を行うと思います。
その質問の中で、
? What do you want to use as your public directory?(public)
というものがあると思います。
これは、「公開するディレクトリとして使いたいものはどれですか?」という質問なのですが、ここでpublicを選択した場合はpublicを、それ以外のbuildなどを選択した場合はそのディレクトリの、index.html
を開きます。
該当のindex.htmlを開くと<body>タグ
の中身が下記のようなコードになっていませんか?
<body>
<div id="message">
<h2>Welcome</h2>
<h1>Firebase Hosting Setup Complete</h1>
<p>You're seeing this because you've successfully setup Firebase Hosting. Now it's time to go build something extraordinary!</p>
<a target="_blank" href="https://firebase.google.com/docs/hosting/">Open Hosting Documentation</a>
</div>
<p id="load">Firebase SDK Loading…</p>
<script>
document.addEventListener('DOMContentLoaded', function() {
const loadEl = document.querySelector('#load');
// // 🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥
// // The Firebase SDK is initialized and available here!
//
// firebase.auth().onAuthStateChanged(user => { });
// firebase.database().ref('/path/to/ref').on('value', snapshot => { });
// firebase.messaging().requestPermission().then(() => { });
// firebase.storage().ref('/path/to/ref').getDownloadURL().then(() => { });
// firebase.analytics(); // call to activate
// firebase.analytics().logEvent('tutorial_completed');
// firebase.performance(); // call to activate
//
// // 🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥
try {
let app = firebase.app();
let features = [
'auth',
'database',
'messaging',
'storage',
'analytics',
'remoteConfig',
'performance',
].filter(feature => typeof app[feature] === 'function');
loadEl.textContent = `Firebase SDK loaded with ${features.join(', ')}`;
} catch (e) {
console.error(e);
loadEl.textContent = 'Error loading the Firebase SDK, check the console.';
}
});
</script>
</body>
これは$ firebase init
をした際に、自動的に生成されたものなのですが、よくみるとなければならないとあるコードがありません。
それが<div id="root"></div>
なのです。
考えられる原因
そもそも、<div id="root"></div>
がなぜなかったのかが謎(わかる方教えてください🙏)なのですが、srcフォルダ内のindex.jsx
では以下のコードで指定された要素(container)のDOMにReactのコンポーネントをレンダリングします。
ReactDOM.render(<App />, document.getElementById('root'));
この時の、ReactDOM.render
の中の第二引数getElementById
がcontainerと呼ばれるそうです。公式ドキュメントに書いてありました...w
ここで、もう一度最初に戻って、エラー文の内容を確認してみましょう。
Error: Target container is not a DOM element.
ここで繋がりましたね。
つまり、
ターゲットのcontainer→document.getElementById('root')
は
DOM要素ではありません
index.html
にはrootというIDをもつ要素が無かったのに、index.jsx
でレンダリングされようとしていた、だからエラーは起きたのでした。