Refreshing the page reveals the complete local storage object

I've successfully created a todo list using Vanilla Javascript along with local storage. The todo list includes the following key-value pairs:

key: todolist
value: [[\"id:0\",\"title:buy groceries\",\"done:false\"], 
[\"id:1\",\"title:pick up dry cleaning\",\"done:false\"], 
[\"id:2\",\"title:walk dog\",\"done:false\"]]

Everything works perfectly on my website, displaying only the titles as intended. However, upon refreshing the page, the entire object is displayed instead.

Pre-refresh:

  • buy groceries
  • pick up dry cleaning
  • walk dog
  • Post-refresh:

  • id:0,title:buy groceries,done:false
  • id:1,title:pick up dry cleaning,done:false
  • id:2,title:walk dog,done:false
  • After a refresh, I wish for only the titles to be displayed within the li tags. This issue only arises after refreshing the page.

    How can I ensure that only the titles display post-refresh?

    I'm fairly new to Javascript and struggling to find a solution. After two days of searching through Google, I'm at my wits' end!

    // establish variables for elements on the page
    const form = document.querySelector('form');
    const ul = document.querySelector('ul');
    const button = document.querySelector('button');
    const input = document.getElementById('item');
    
    // address empty array when script runs by checking if localStorage exists
    let itemsArray;
    if (localStorage.getItem('todolist')) {
        itemsArray = JSON.parse(localStorage.getItem('todolist'));
    } else {
        itemsArray = [];
    }
    
    localStorage.setItem('todolist', JSON.stringify(itemsArray));
    const data = JSON.parse(localStorage.getItem('todolist'));
    
    // function that creates an li element, sets the text, and appends it to the ul
    const liMaker = (text) => {
        const li = document.createElement('li');
        li.textContent = text;
        ul.appendChild(li);
    
        // create a "close" button and append it to each list item
        var span = document.createElement("SPAN");
        var txt = document.createTextNode("🗑️");
    
        span.className = "close";
        span.appendChild(txt);
        li.appendChild(span);
    
        for (i = 0; i < close.length; i++) {
            close[i].onclick = function() {
                var div = this.parentElement;
                div.style.display = "none";
            }
        }
    }
    
    // define event listener to submit the input value
    form.addEventListener('submit', function(e) {
        e.preventDefault();
    
        var id = "id:" + itemsArray.length;
        var title = "title:" + input.value;
        var done = "done:" + "false";
    
        itemsArray.push([id, title, done]);
        localStorage.setItem('todolist', JSON.stringify(itemsArray));
        liMaker(input.value);
        input.value = ""; 
    });
    
    data.forEach(item => {
        liMaker(item);
    });
    
    // clear items from todolist
    button.addEventListener('click', function () {
        localStorage.removeItem("todolist");
        while (ul.firstChild) {
            ul.removeChild(ul.firstChild);
        }
        itemsArray = [];
    });
    

    One thing worth noting is that the page refresh issue doesn't occur when I change the following line of code:

    itemsArray.push([id, title, done]);

    to the following:

    itemsArray.push(input.value);

    Answer №1

    If you are encountering this issue, it is likely due to an incorrect JSON format causing problems with your data handling.
    The reason for the problem only showing up on page refresh is that the local storage retains improperly structured JSON under the "todolist" key. This flawed JSON value gets stored in your data variable and leads to undesired output in your list items.

    When the page is not refreshed, the text of your list items comes directly from the input field text.

    To resolve this, make the advised changes below to ensure correct functionality (confirmed via testing). Hoping this solution proves effective for you.

    JavaScript notes

    Please note, if your JavaScript comments span multiple lines, each line should begin with //.

    For instance, instead of:

    //function that creates an li element, sets the text of the element to the 
    parameter, and appends the list item to the ul.
    

    You should write:

    //function that creates an li element, sets the text of the element to the 
    //parameter, and appends the list item to the ul.
    

    JSON format correction

    An issue also lies in the formatting of your JSON. It should resemble this structure:

    [{"id":0,"title":"buy groceries","done":false}, 
    {"id":1,"title":"pick up dry cleaning","done":false},
    {"id":2,"title":"walk dog","done":false}]
    

    Each property name (e.g., "id", "title", "done") should be enclosed in double quotes, while property values (e.g., "buy groceries") must also be within quotes unless they are integers or booleans. Validate your JSON using a tool like JSLint.

    To ensure proper JSON format upon form submission, update these code lines:

    var id = "id:" + itemsArray.length;
    var title = "title:" + input.value;
    var done = "done:" + "false";
    itemsArray.push([id, title, done]);
    

    To:

    var idValue = itemsArray.length;
    var titleValue = input.value;
    var doneValue = false;
    itemsArray.push({"id": idValue, "title": titleValue, "done" : doneValue});
    

    Looping through the array

    The data variable contains an array of todolist objects fetched from local storage. Thus, the item in your code will represent the entire object, e.g.,

    {"id":0, "title":"buy groceries", "done":false}
    . To access the title correctly, use item.title as shown below:

    data.forEach(item => {
        //log the item to check it
        console.log(item);
        liMaker(item.title);
      });
    

    Similar questions

    If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

    What is the reason for this JavaScript code not activating the input field (aspx)?

    Thank you for taking the time to review this. I understand that for most of you client side scripting experts, this task is a breeze. However, all I am trying to achieve is to display a message at the top notifying the user that their click has been regist ...

    Error: React cannot render objects as children

    I am encountering an error that I cannot seem to figure out. The issue seems to be with the following line of code: <p className="bold blue padding-left-30">{question}</p> Specifically, it does not like the usage of {question} in the above pa ...

    No specification has been provided for the delivery

    I'm currently working with the Meteor framework and I am attempting to send an uploaded file (HTML input) from the client to the server using the npm package Delivery. Below is my code: Client side : var socket = io.connect('http://0.0.0.0 ...

    NodeJS - Issue: The procedure specified could not be located in the bcrypt_lib.node

    After upgrading from Node.js 0.12.7 to 4.2.1, I encountered an error when attempting to start my server: $ node server.js C:\Users\me\documents\github\angular-express-auth\node_modules\bcrypt\node_modules\bindi ...

    Understanding the distinction between deleting and nullifying in JavaScript

    var obj = {type: "beetle", price : "xxx", popular: "yes" ,.... }; If I want to remove all the properties from obj, what is the correct way to do it? Should I use delete obj.type; delete obj.price; delete obj.popular ... and so on. Or should I set ob ...

    The method window.scrollTo() may encounter issues when used with overflow and a height set to 100vh

    Suppose I have an HTML structure like this and I need to create a button for scrolling using scrollTo. However, I've come across the information that scrollTo doesn't work well with height: 100vh and overflow: auto. What would be the best way to ...

    Is it possible to create a carousel using a JQuery slideshow that connects the first and last list elements?

    I am working on creating a carousel effect with three list elements that should slide in and out of the container when the left or right arrows are clicked. I want the list elements to wrap so that when the last element is reached, it goes back to the firs ...

    Concealing applicationId and clientToken in Datadog

    I'm currently using an Angular application and I've integrated it with the Datadog application to utilize Session and Replay (RUM). However, I am concerned about the security of my sensitive information such as applicationId and clientToken. Is t ...

    Unsuccessful attempt at testing RequireJS in a straightforward manner

    As a beginner in RequireJS, I am currently experimenting to gain some experience. My goal is to make require load basic Angular first and then manually bring in Angular UI Bootstrap. However, I am encountering an issue where UI Bootstrap complains that ang ...

    Interactive quiz program based on object-oriented principles

    As I work on developing a quiz app using JavaScript, everything seems to be going well. However, I've encountered an issue with validation where my code is validating the answers twice - once with the correct answer from the previous question and agai ...

    Guide to managing AutoComplete {onChange} in MUI version 5 with a personalized hook

    Currently, I am utilizing a custom hook that manages the validation and handling of the onChange function. For most components like input, select, and textField, I have no trouble with handling the onChange event using the syntax below: The code snippet ...

    Unlocking the attributes of Angular form elements: A guide

    Imagine we have a form like this <form name="myForm" data-ng-controller="Ctrl"> <input name="input" data-ng-model="userType" data-description="User Type" required> </form> When working in the controller, we can refer to the input el ...

    What are the best ways to make this date more visually appealing and easy to understand?

    Hey there! So I have a date that looks like this: 2022-06-28T17:09:00.922108+01:00 I'm trying to make it more readable, but unfortunately, when I attempted using moment-js in my javascript/react project, it threw an error stating "invalid format". ...

    Create a personalized and distinct name following the submission of data into multiple text fields either through Nuxt/Vue or by utilizing pure JavaScript

    In my new app, users can register packages and then participate in a ballot session where the package will be assigned to someone else. To make this process smoother, I want each ballot session or box to have a unique Ballot ID attached to it. For example ...

    "Create a smooth transition effect in CSS by fading out one div and fading in

    I've set up a grid of buttons, and my goal is to have the grid fade out when a button is clicked, then fade in with a new div in its place. This involves animating opacity from 1 to 0 and vice versa while toggling the display:none property for content ...

    Issue: Unable to access 'filter' property of null object

    I've been working on a small react dropdown task and it's running smoothly in Google Chrome. However, I encountered an error when testing it on MS Explorer. Even after deploying it on a live server, the issue persisted. The specific error message ...

    How can you access the URL of an ajax request in JavaScript/jQuery once the request has been completed?

    I am currently working on a web program using JavaScript that involves making multiple ajax calls. I am faced with the challenge of figuring out how to retrieve the URL after making an ajax call to the specified URL. These ajax calls are made within a for ...

    Create a compressed package of a Vue project that can easily be inserted into a Blogger blog post as a single HTML file

    Is there a way to package all the files related to a Vue.js project (HTML, JavaScript, CSS) into one single HTML file for easy deployment on a Blogger Blogspot post? In the past, a question similar to this was asked regarding bundling files into a single ...

    Ways to store a filestream coming from Node.js into AngularJS

    When using my express server, I have a post-request set up to retrieve a pdf file from Amazon S3 and then send it back to Angular. This is the endpoint in my express server: var fileStream = s3.getObject(options).createReadStream(); fileStream.pipe(res); ...

    Dealing with Javascript exceptions and sending email notifications in Django

    I appreciate the traditional method of handling server-side exceptions in Django using Python. I am interested in finding a similar approach for client-side exception handling in JavaScript. So far, I have come across only one option which is DamnIT, but ...