Loading items for an eCommerce site I am attempting to make an eCommerce site from scratch. Right now I have the following code that gets all the items from a Firebase Firestore database and then adds HTML into an items div element based on the item's info.

var items = [];
var itemsDiv = document.getElementsByClassName("items")[0];

db.collection("items").get().then((querySnapshot) =&gt; {
    querySnapshot.forEach((doc) =&gt; {
        var docData = doc.data();
        items.push(docData);
    });
    renderItems();
});

function renderItems() {
  console.log(items);
  items.forEach(function(item) {
    itemsDiv.innerHTML += `
    &lt;div class="item"&gt;
      &lt;img class="itemImgBackground" src="assets/${item.name.replace(" ", "")}.png"&gt;
      &lt;img class="itemImg" src="assets/${item.name.replace(" ", "")}.png"&gt;
      &lt;span class="itemName"&gt;${item.name}&lt;/span&gt;
      &lt;span class="itemCondition"&gt;${item.condition}&lt;/span&gt;
      &lt;span class="itemPrice"&gt;${item.price}&lt;/span&gt;
    &lt;/div&gt;
    `
  });
}


What can I do to make my code better?
Here are a few things:


good you're using ` (template literals) to format your HTML inside the JavaScript code
don't use innerHTML += as it forces the browser to re-render the DOM when called. Read more here: Why is Element.innerHTML += bad code?. Instead create an HTML element with .createElement and append it to an existing DOM element .appendChild. 

So instead of appending the the HTML string &lt;div class="item"&gt;...&lt;/div&gt; to the parent div you can:


create a wrapping div element:

const div = document.createElement('div');

append the HTML string to the div wrapper (remember div is an object of type Element but it's not already rendered in the page DOM). You can use all of Element's methods on it, including .innerHTML:

div.innerHTML = `
  &lt;div class="item"&gt;
    ...
  &lt;/div&gt;
`;

then append the wrapper's first child to the parent element:

divParent.appendChild(div);


you can use .querySelectorAll instead of .getELementByClassName. The former allows you to pass in an actual CSS selector instead of a className (the latter method). In your case you only want the first matching element, so use .querySelector instead.
I always use single quotes ' for JavaScript strings and double quotes " when I need quotes inside the strings e.g. with HTML attributes. That's personal preference though.
no need to define the variable docData as doc.data() is already pretty self-explanatory
you can use arrow functions outside also (arg1, arg2, ...) =&gt; {} or if you have a single argument arg =&gt; {} (no need for the parenthesis).
you could use const for constant variable to make sure they don't get their values changed: for instance itemsDiv (fyi: renamed to itemsParent for clarity) can be defined with const instead of var.




Here's a possible refactoring of your code:

const itemsParent = document.querySelector('.items')[0];
let items = [];

const renderItems = items =&gt; {

  items.forEach(item =&gt; {

    const div = document.createElement('div');

    div.innerHTML = `
      &lt;div class="item"&gt;
        &lt;img class="itemImgBackground" src="assets/${item.name.replace(" ", "")}.png"&gt;
        &lt;img class="itemImg" src="assets/${item.name.replace(" ", "")}.png"&gt;
        &lt;span class="itemName"&gt;${item.name}&lt;/span&gt;
        &lt;span class="itemCondition"&gt;${item.condition}&lt;/span&gt;
        &lt;span class="itemPrice"&gt;${item.price}&lt;/span&gt;
      &lt;/div&gt;
    `.trim();

    itemsParent.appendChild(div.firstChild);

  });
}

db.collection('items').get().then((querySnapshot) =&gt; {

  querySnapshot.forEach(doc =&gt; {
    items.push(doc.data());
  });

  renderItems(items);

});




Edit: testing div creation, it appears you need to trim the string first:



const div = document.createElement('div');
div.innerHTML = `
  &lt;div class="parent"&gt;
    &lt;div class="child"&gt;&lt;/div&gt;
  &lt;/div&gt;
`.trim();

console.log(div.outerHTML)
console.log(div.firstChild.outerHTML)