Reactユーザーのみなさんこんにちは。
普段はGoを書いていてあるタイミングでReactのプログラムを保守することになり、その時に出くわしたエラーと原因について書いていきます。
事件はブラウザの翻訳機能で起きた
皆さんが使うブラウザでは自動翻訳機能があると思います。
翻訳の仕組みとしては仕組みとしては翻訳機能をOnにするとブラウザ内の文をサーバーに送ってレスポンスからDOMの置き換えを実行しているような感じでした。
(しっかりとは調べていません)
そんな中でDOM操作をしまくっていたところ、翻訳機能をOnにした状態で操作したときに以下のエラーが発生しました。
Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
解消方法の模索
とりあえずググってみたところ近い問題を持っている人はいたようだった。
このissueではdivタグ内に直接文字列を書くことに起因してエラーが起きるようだった。
うちのコードそんなの無いんだけど???
もう少し読んでみた
上記のリンクのissueにも書いてあるがもう少し説明を見ているがエラーをスローする/しないは以下の条件となっていた。
テキストノードの条件レンダリング: テキストノードが親要素の子要素として単独で存在せず、かつ条件レンダリングされていた場合にReactはエラーを発生させます。これは、テキストノードが削除される際に、親要素から子要素を削除する処理 (parent.removeChild(textNode)) が実行されますが、既にテキストノードは親要素の子要素ではないためエラーが発生してしまうためです。
唯一の子要素のテキストノード: もし、条件レンダリングされるテキストノードが親要素の唯一の子要素であれば、Reactはエラーを発生させません。
テキストノードの前方のノードの条件レンダリング: テキストノードの前方に位置するノードが条件レンダリングされていた場合にも、Reactはエラーを発生させます。このケースでは、新しいノードが挿入される際に、親要素に対して挿入処理 (parent.insertBefore(someNode, textNode)) が実行されますが、テキストノードは既に親要素の子要素ではないためエラーが発生してしまいます。
一方で我々が書いた個所は以下のようなコードだった。
const Component = () => {
return (
<button>
{condition && 'Welcome'}
<span>Something</span>
</button>
)
}
このコードは上記の条件の中で「テキストノードが親要素の子要素として単独で存在せず、かつ条件レンダリングされていた場合」に該当していたためエラーが発生していた。
divタグに限らず、buttonタグやでも発生するので注意が必要だった。