In my example, I’m trying to fetch data from the server and save it to the document as text in the <p> element. Everything works fine except that the appendChild method doesn’t seem to work as it should. Here is a sample of my code and the error message:
(async () => { let resp = await fetch("/shaders", { method: "GET" }); let txt = await resp.text(); let elm = document.createElement("p").innerHTML = txt; console.log(txt) // Hello Stack Overflow! // logs the message as expected document.body.appendChild(elm) // error occurs })()
With error message: Uncaught (in promise) TypeError: Node.appendChild: Argument 1 is not an object, at line 10.
Does anyone know what is causing this problem?
—
Note: With the append method it works just fine
Advertisement
Answer
From the MDN docs on the JavaScript assignment operator:
Chaining the assignment operator is possible in order to assign a single value to multiple variables.
So,
let elm = document.createElement("p").innerHTML = txt; // The above has the same effect as doing the following: document.createElement("p").innerHTML = txt; let elm = txt;
elm
gets assigned text, which Node.appendChild
does not accept as an argument type (although Element.append
does, which you noticed but perhaps didn’t fully understand why).
I’m guessing you intended to do this:
let elm = document.createElement("p"); elm.textContent = txt;
Note that I used Node.textContent
instead of Element.innerHTML
. The MDN docs state the differences
Element.innerHTML returns HTML, as its name indicates. Sometimes people use innerHTML to retrieve or write text inside an element, but textContent has better performance because its value is not parsed as HTML.
Moreover, using textContent can prevent XSS attacks.
If you really need to use innerHTML
or innerText
and the resource you are fetching is not always controlled by you, you probably want to do some kind of sanitization to protect against XSS.