1

I have a working code that fetches JSON data and adds it to the HTML element div. I am using innerHTML to add data. Since using innerHTML is a bad practice I am looking for suggestions regarding the best practice to add the JSON data to any HTML element without using innerHTML? Thanks in advance.

const API_URL = "http://localhost:3000/api/posts";
const API_BASE_URL = "http://localhost:3000/";

window.onload = () => {
    getPosts();
}

const getPosts = () => {
    fetch(API_URL, {
        method: 'GET'
    }).then((response) => {
        return response.json();
    }).then((data) => {
        buildPosts(data);
    })
}

const buildPosts = (blogPosts) => {
    let blogPostsContent = "";
    for(blogPost of blogPosts){
        const postDate = new Date(parseInt(blogPost.added_date)).toDateString();
        blogPostsContent += `
        <div class="post">
            <div class="post-image"> </div>
            <div class="post-content"> 
                <div class="post-date">${postDate}</div>
                <div class="post-title"><h4>${blogPost.title}</h4></div>
                <div class="post-text">${blogPost.content}</div> 
            </div>
        </div>`
    }

    document.querySelector('.blog-posts').innerHTML = blogPostsContent;
}
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>My Blog</title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="style/style.css">
    </head>
    <body>
        <div class="add-post">
            <a href="new-post.html">
                <div class="nav-button new-post-button">+</div>
            </a>
        </div>
        <header>
            <div class="profile-image"></div>
            <div class="profile-name">Puja Patel</div>
            <div class="subtext">Welcome to my blog!</div>
        </header>
        <div class="main">
            <div class="main-container blog-posts">
                <div class="post">
                    <div class="post-image"> </div>
                    <div class="post-content"> 
                        <div class="post-date">Mar 10</div>
                        <div class="post-title"><h4>This is my title</h4></div>
                        <div class="post-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled</div> 
                    </div>
                </div>
            </div>
        </div>
        <footer>
            <p>Made with love!!</p>
        </footer>
        <script src="js/index.js"></script>
    </body>
</html>
pooja gajera
  • 373
  • 4
  • 20

1 Answers1

1

Using .innerHTML by itself isn't bad, but using .innerHTML with arbitrary external input (such as from an API, or from the user) is a bad idea because it can open you up to arbitrary code execution. It can also lead to unexpected elements being created in the document, and odd display issues if the stuff that's inserted happens to have HTML markup.

In your case, to fix it, you can set the innerHTML to the HTML markup of the <div class="post", and insert the postDate, title, and content into the .textContent of the child divs afterwards:

const buildPosts = (blogPosts) => {
    const postsContainer = document.querySelector('.blog-posts')
    for(const blogPost of blogPosts){
        const postDate = new Date(parseInt(blogPost.added_date)).toDateString();
        const newPost = postsContainer.appendChild(document.createElement('div'));
        newPost.className = 'post';
        newPost.innerHTML = `
            <div class="post-image"> </div>
            <div class="post-content"> 
                <div class="post-date"></div>
                <div class="post-title"><h4></h4></div>
                <div class="post-text"></div> 
            </div>`;
        const contentDivs = newPost.querySelector('.post-content').children;
        contentDivs[0].textContent = postDate;
        contentDivs[1].children[0].textContent = blogPost.title;
        contentDivs[2].textContent = blogPost.content;
    }
}

If the data from the API will always be completely trustworthy, using innerHTML is fine.

If the data contains HTML markup that needs to be inserted but is not necessarily trustworthy, you'll want to sanitize it to ensure no unexpected scripts run. If sanitized properly, using innerHTML is OK.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320